diff --git a/.circleci/config.yml b/.circleci/config.yml index 9aae18f7534..be11604af24 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -15,6 +15,6 @@ jobs: - run: go install -v . && go get -u github.com/vektah/dataloaden github.com/pkg/errors - run: go generate ./... && if [[ $(git --no-pager diff) ]] ; then echo "you need to run go generate" ; git --no-pager diff ; exit 1 ; fi - run: go vet ./... - - run: go test -race ./... + - run: go test ./... - run: gometalinter --vendor ./... diff --git a/.gitignore b/.gitignore index ef6c1c9770e..c82d6fe033c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,7 @@ -/internal/tests/testdata/graphql-js /vendor /docs/public /example/chat/node_modules /example/chat/package-lock.json -/codegen/testdata/gen +/codegen/tests/gen .idea/ diff --git a/Gopkg.lock b/Gopkg.lock index f23744ee67e..ee8ef62b2c0 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1,6 +1,14 @@ # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. +[[projects]] + branch = "master" + digest = "1:99b2e09d42b4d0929e9e6ac496922f5221baa79b60968576d5ce310b44640c3b" + name = "github.com/agnivade/levenshtein" + packages = ["."] + pruneopts = "UT" + revision = "1787a73e302ce294513cfab1982e186f5cf8985f" + [[projects]] digest = "1:a2c1d0e43bd3baaa071d1b9ed72c27d78169b2b269f71c105ac4ba34b1be4a39" name = "github.com/davecgh/go-spew" @@ -142,6 +150,22 @@ pruneopts = "UT" revision = "314ac81052eedc03ac0a79bdc89d05a49a2a5814" +[[projects]] + branch = "master" + digest = "1:f03ae2a33628fa4fc2d6b9e5ea9630ace11ba730a808dff0674f6ee7137c2bc1" + name = "github.com/vektah/gqlparser" + packages = [ + ".", + "ast", + "gqlerror", + "lexer", + "parser", + "validator", + "validator/rules", + ] + pruneopts = "UT" + revision = "8236ac024f533cfa991e494ac0e4ead587c10f8e" + [[projects]] branch = "master" digest = "1:76ee51c3f468493aff39dbacc401e8831fbb765104cbf613b89bef01cf4bad70" @@ -210,6 +234,9 @@ "github.com/stretchr/testify/assert", "github.com/stretchr/testify/require", "github.com/vektah/dataloaden", + "github.com/vektah/gqlparser", + "github.com/vektah/gqlparser/ast", + "github.com/vektah/gqlparser/gqlerror", "golang.org/x/tools/go/loader", "golang.org/x/tools/imports", "gopkg.in/yaml.v2", diff --git a/appveyor.yml b/appveyor.yml index fc40eb339eb..5dd4766709d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -13,7 +13,7 @@ environment: PATH: '%PATH%;c:\gopath\bin' branches: - only: ["master"] + only: ["master", "next"] init: - git config --global core.autocrlf input diff --git a/client/websocket.go b/client/websocket.go index 555ddd5b9e6..e4e06051339 100644 --- a/client/websocket.go +++ b/client/websocket.go @@ -6,7 +6,7 @@ import ( "strings" "github.com/gorilla/websocket" - "github.com/vektah/gqlgen/neelance/errors" + "github.com/vektah/gqlparser/gqlerror" ) const ( @@ -83,7 +83,7 @@ func (p *Client) Websocket(query string, options ...Option) *Subscription { } if respDataRaw["errors"] != nil { - var errs []*errors.QueryError + var errs []*gqlerror.Error if err = unpack(respDataRaw["errors"], errs); err != nil { return err } diff --git a/codegen/build.go b/codegen/build.go index d56fc06f1f5..6eb6dba8f8b 100644 --- a/codegen/build.go +++ b/codegen/build.go @@ -84,42 +84,19 @@ func (cfg *Config) bind() (*Build, error) { SchemaRaw: cfg.SchemaStr, } - if qr, ok := cfg.schema.EntryPoints["query"]; ok { - b.QueryRoot = b.Objects.ByName(qr.TypeName()) - } - - if mr, ok := cfg.schema.EntryPoints["mutation"]; ok { - b.MutationRoot = b.Objects.ByName(mr.TypeName()) + if cfg.schema.Query != nil { + b.QueryRoot = b.Objects.ByName(cfg.schema.Query.Name) + } else { + return b, fmt.Errorf("query entry point missing") } - if sr, ok := cfg.schema.EntryPoints["subscription"]; ok { - b.SubscriptionRoot = b.Objects.ByName(sr.TypeName()) + if cfg.schema.Mutation != nil { + b.MutationRoot = b.Objects.ByName(cfg.schema.Mutation.Name) } - if b.QueryRoot == nil { - return b, fmt.Errorf("query entry point missing") + if cfg.schema.Subscription != nil { + b.SubscriptionRoot = b.Objects.ByName(cfg.schema.Subscription.Name) } - - // Poke a few magic methods into query - q := b.Objects.ByName(b.QueryRoot.GQLType) - q.Fields = append(q.Fields, Field{ - Type: &Type{namedTypes["__Schema"], []string{modPtr}, nil}, - GQLName: "__schema", - NoErr: true, - GoMethodName: "ec.introspectSchema", - Object: q, - }) - q.Fields = append(q.Fields, Field{ - Type: &Type{namedTypes["__Type"], []string{modPtr}, nil}, - GQLName: "__type", - NoErr: true, - GoMethodName: "ec.introspectType", - Args: []FieldArgument{ - {GQLName: "name", Type: &Type{namedTypes["String"], []string{}, nil}, Object: &Object{}}, - }, - Object: q, - }) - return b, nil } diff --git a/codegen/codegen.go b/codegen/codegen.go index 789ef2ecb05..d0e1cb8a506 100644 --- a/codegen/codegen.go +++ b/codegen/codegen.go @@ -11,7 +11,8 @@ import ( "github.com/pkg/errors" "github.com/vektah/gqlgen/codegen/templates" - "github.com/vektah/gqlgen/neelance/schema" + "github.com/vektah/gqlgen/graphql/introspection" + "github.com/vektah/gqlparser" "golang.org/x/tools/imports" ) @@ -82,12 +83,12 @@ func (cfg *Config) normalize() error { } builtins := TypeMap{ - "__Directive": {Model: "github.com/vektah/gqlgen/neelance/introspection.Directive"}, - "__Type": {Model: "github.com/vektah/gqlgen/neelance/introspection.Type"}, - "__Field": {Model: "github.com/vektah/gqlgen/neelance/introspection.Field"}, - "__EnumValue": {Model: "github.com/vektah/gqlgen/neelance/introspection.EnumValue"}, - "__InputValue": {Model: "github.com/vektah/gqlgen/neelance/introspection.InputValue"}, - "__Schema": {Model: "github.com/vektah/gqlgen/neelance/introspection.Schema"}, + "__Directive": {Model: "github.com/vektah/gqlgen/graphql/introspection.Directive"}, + "__Type": {Model: "github.com/vektah/gqlgen/graphql/introspection.Type"}, + "__Field": {Model: "github.com/vektah/gqlgen/graphql/introspection.Field"}, + "__EnumValue": {Model: "github.com/vektah/gqlgen/graphql/introspection.EnumValue"}, + "__InputValue": {Model: "github.com/vektah/gqlgen/graphql/introspection.InputValue"}, + "__Schema": {Model: "github.com/vektah/gqlgen/graphql/introspection.Schema"}, "Int": {Model: "github.com/vektah/gqlgen/graphql.Int"}, "Float": {Model: "github.com/vektah/gqlgen/graphql.Float"}, "String": {Model: "github.com/vektah/gqlgen/graphql.String"}, @@ -106,8 +107,9 @@ func (cfg *Config) normalize() error { } } - cfg.schema = schema.New() - return cfg.schema.Parse(cfg.SchemaStr) + var err error + cfg.schema, err = gqlparser.LoadSchema(introspection.Prelude + cfg.SchemaStr) + return err } var invalidPackageNameChar = regexp.MustCompile(`[^\w]`) diff --git a/codegen/config.go b/codegen/config.go index cd42ae6bfc4..15fdf93eb99 100644 --- a/codegen/config.go +++ b/codegen/config.go @@ -9,7 +9,7 @@ import ( "strings" "github.com/pkg/errors" - "github.com/vektah/gqlgen/neelance/schema" + "github.com/vektah/gqlparser/ast" "gopkg.in/yaml.v2" ) @@ -60,7 +60,7 @@ type Config struct { Model PackageConfig `yaml:"model"` Models TypeMap `yaml:"models,omitempty"` - schema *schema.Schema `yaml:"-"` + schema *ast.Schema `yaml:"-"` } type PackageConfig struct { diff --git a/codegen/config_test.go b/codegen/config_test.go index e4161d9c31d..fabd3242d7e 100644 --- a/codegen/config_test.go +++ b/codegen/config_test.go @@ -17,12 +17,12 @@ func TestLoadConfig(t *testing.T) { }) t.Run("malformed config", func(t *testing.T) { - _, err := LoadConfig("testdata/cfg/malformedconfig.yml") + _, err := LoadConfig("tests/cfg/malformedconfig.yml") require.EqualError(t, err, "unable to parse config: yaml: unmarshal errors:\n line 1: cannot unmarshal !!str `asdf` into codegen.Config") }) t.Run("unknown keys", func(t *testing.T) { - _, err := LoadConfig("testdata/cfg/unknownkeys.yml") + _, err := LoadConfig("tests/cfg/unknownkeys.yml") require.EqualError(t, err, "unable to parse config: yaml: unmarshal errors:\n line 2: field unknown not found in type codegen.Config") }) } @@ -33,7 +33,7 @@ func TestLoadDefaultConfig(t *testing.T) { var cfg *Config t.Run("will find closest match", func(t *testing.T) { - err = os.Chdir(filepath.Join(testDir, "testdata", "cfg", "subdir")) + err = os.Chdir(filepath.Join(testDir, "tests", "cfg", "subdir")) require.NoError(t, err) cfg, err = LoadDefaultConfig() @@ -42,7 +42,7 @@ func TestLoadDefaultConfig(t *testing.T) { }) t.Run("will find config in parent dirs", func(t *testing.T) { - err = os.Chdir(filepath.Join(testDir, "testdata", "cfg", "otherdir")) + err = os.Chdir(filepath.Join(testDir, "tests", "cfg", "otherdir")) require.NoError(t, err) cfg, err = LoadDefaultConfig() diff --git a/codegen/enum_build.go b/codegen/enum_build.go index f2e6f63cb44..6ea1efcad7b 100644 --- a/codegen/enum_build.go +++ b/codegen/enum_build.go @@ -5,22 +5,21 @@ import ( "strings" "github.com/vektah/gqlgen/codegen/templates" - "github.com/vektah/gqlgen/neelance/schema" + "github.com/vektah/gqlparser/ast" ) func (cfg *Config) buildEnums(types NamedTypes) []Enum { var enums []Enum for _, typ := range cfg.schema.Types { - namedType := types[typ.TypeName()] - e, isEnum := typ.(*schema.Enum) - if !isEnum || strings.HasPrefix(typ.TypeName(), "__") || namedType.IsUserDefined { + namedType := types[typ.Name] + if typ.Kind != ast.Enum || strings.HasPrefix(typ.Name, "__") || namedType.IsUserDefined { continue } var values []EnumValue - for _, v := range e.Values { - values = append(values, EnumValue{v.Name, v.Desc}) + for _, v := range typ.EnumValues { + values = append(values, EnumValue{v.Name, v.Description}) } enum := Enum{ diff --git a/codegen/import_build.go b/codegen/import_build.go index f0877ed3d42..7ed7b4e9208 100644 --- a/codegen/import_build.go +++ b/codegen/import_build.go @@ -18,12 +18,12 @@ var ambientImports = []string{ "strconv", "time", "sync", - "github.com/vektah/gqlgen/neelance/introspection", - "github.com/vektah/gqlgen/neelance/errors", - "github.com/vektah/gqlgen/neelance/query", - "github.com/vektah/gqlgen/neelance/schema", - "github.com/vektah/gqlgen/neelance/validation", + "errors", + + "github.com/vektah/gqlparser", + "github.com/vektah/gqlparser/ast", "github.com/vektah/gqlgen/graphql", + "github.com/vektah/gqlgen/graphql/introspection", } func buildImports(types NamedTypes, destDir string) *Imports { diff --git a/codegen/import_test.go b/codegen/import_test.go index 0e55887430e..471aa067978 100644 --- a/codegen/import_test.go +++ b/codegen/import_test.go @@ -15,7 +15,7 @@ func TestInvalidPackagenames(t *testing.T) { id: Int! } `, TypeMap{ - "InvalidIdentifier": {Model: "github.com/vektah/gqlgen/codegen/testdata/invalid-packagename.InvalidIdentifier"}, + "InvalidIdentifier": {Model: "github.com/vektah/gqlgen/codegen/tests/invalid-packagename.InvalidIdentifier"}, }) require.NoError(t, err) @@ -31,7 +31,7 @@ func TestImportCollisions(t *testing.T) { } `, TypeMap{ - "It": {Model: "github.com/vektah/gqlgen/codegen/testdata/introspection.It"}, + "It": {Model: "github.com/vektah/gqlgen/codegen/tests/introspection.It"}, }) require.NoError(t, err) diff --git a/codegen/input_build.go b/codegen/input_build.go index 98b25b8b21d..6dd58d4a3a1 100644 --- a/codegen/input_build.go +++ b/codegen/input_build.go @@ -6,7 +6,7 @@ import ( "strings" "github.com/pkg/errors" - "github.com/vektah/gqlgen/neelance/schema" + "github.com/vektah/gqlparser/ast" "golang.org/x/tools/go/loader" ) @@ -14,8 +14,8 @@ func (cfg *Config) buildInputs(namedTypes NamedTypes, prog *loader.Program, impo var inputs Objects for _, typ := range cfg.schema.Types { - switch typ := typ.(type) { - case *schema.InputObject: + switch typ.Kind { + case ast.InputObject: input, err := buildInput(namedTypes, typ) if err != nil { return nil, err @@ -44,18 +44,22 @@ func (cfg *Config) buildInputs(namedTypes NamedTypes, prog *loader.Program, impo return inputs, nil } -func buildInput(types NamedTypes, typ *schema.InputObject) (*Object, error) { - obj := &Object{NamedType: types[typ.TypeName()]} +func buildInput(types NamedTypes, typ *ast.Definition) (*Object, error) { + obj := &Object{NamedType: types[typ.Name]} - for _, field := range typ.Values { + for _, field := range typ.Fields { newField := Field{ - GQLName: field.Name.Name, + GQLName: field.Name, Type: types.getType(field.Type), Object: obj, } - if field.Default != nil { - newField.Default = field.Default.Value(nil) + if field.DefaultValue != nil { + var err error + newField.Default, err = field.DefaultValue.Value(nil) + if err != nil { + return nil, errors.Errorf("default value for %s.%s is not valid: %s", typ.Name, field.Name, err.Error()) + } } if !newField.Type.IsInput && !newField.Type.IsScalar { @@ -70,7 +74,7 @@ func buildInput(types NamedTypes, typ *schema.InputObject) (*Object, error) { // if user has implemented an UnmarshalGQL method on the input type manually, use it // otherwise we will generate one. -func buildInputMarshaler(typ *schema.InputObject, def types.Object) *Ref { +func buildInputMarshaler(typ *ast.Definition, def types.Object) *Ref { switch def := def.(type) { case *types.TypeName: namedType := def.Type().(*types.Named) diff --git a/codegen/input_test.go b/codegen/input_test.go index 62e157b1a69..a5fecc2bd7c 100644 --- a/codegen/input_test.go +++ b/codegen/input_test.go @@ -57,7 +57,7 @@ func TestRecursiveInputType(t *testing.T) { self: [RecursiveInputSlice!] } `, TypeMap{ - "RecursiveInputSlice": {Model: "github.com/vektah/gqlgen/codegen/testdata.RecursiveInputSlice"}, + "RecursiveInputSlice": {Model: "github.com/vektah/gqlgen/codegen/tests.RecursiveInputSlice"}, }) require.NoError(t, err) diff --git a/codegen/interface_build.go b/codegen/interface_build.go index cdf0f59724b..5ffcbcedab8 100644 --- a/codegen/interface_build.go +++ b/codegen/interface_build.go @@ -7,18 +7,15 @@ import ( "sort" "strings" - "github.com/vektah/gqlgen/neelance/schema" + "github.com/vektah/gqlparser/ast" "golang.org/x/tools/go/loader" ) func (cfg *Config) buildInterfaces(types NamedTypes, prog *loader.Program) []*Interface { var interfaces []*Interface for _, typ := range cfg.schema.Types { - switch typ := typ.(type) { - case *schema.Union, *schema.Interface: + if typ.Kind == ast.Union || typ.Kind == ast.Interface { interfaces = append(interfaces, cfg.buildInterface(types, typ, prog)) - default: - continue } } @@ -29,39 +26,19 @@ func (cfg *Config) buildInterfaces(types NamedTypes, prog *loader.Program) []*In return interfaces } -func (cfg *Config) buildInterface(types NamedTypes, typ schema.NamedType, prog *loader.Program) *Interface { - switch typ := typ.(type) { +func (cfg *Config) buildInterface(types NamedTypes, typ *ast.Definition, prog *loader.Program) *Interface { + i := &Interface{NamedType: types[typ.Name]} - case *schema.Union: - i := &Interface{NamedType: types[typ.TypeName()]} + for _, implementor := range cfg.schema.GetPossibleTypes(typ) { + t := types[implementor.Name] - for _, implementor := range typ.PossibleTypes { - t := types[implementor.TypeName()] - - i.Implementors = append(i.Implementors, InterfaceImplementor{ - NamedType: t, - ValueReceiver: cfg.isValueReceiver(types[typ.Name], t, prog), - }) - } - - return i - - case *schema.Interface: - i := &Interface{NamedType: types[typ.TypeName()]} - - for _, implementor := range typ.PossibleTypes { - t := types[implementor.TypeName()] - - i.Implementors = append(i.Implementors, InterfaceImplementor{ - NamedType: t, - ValueReceiver: cfg.isValueReceiver(types[typ.Name], t, prog), - }) - } - - return i - default: - panic(fmt.Errorf("unknown interface %#v", typ)) + i.Implementors = append(i.Implementors, InterfaceImplementor{ + NamedType: t, + ValueReceiver: cfg.isValueReceiver(types[typ.Name], t, prog), + }) } + + return i } func (cfg *Config) isValueReceiver(intf *NamedType, implementor *NamedType, prog *loader.Program) bool { diff --git a/codegen/interface_test.go b/codegen/interface_test.go index 175f53c6b2e..ce75507e384 100644 --- a/codegen/interface_test.go +++ b/codegen/interface_test.go @@ -26,10 +26,10 @@ func TestShapes(t *testing.T) { } union ShapeUnion = Circle | Rectangle `, TypeMap{ - "Shape": {Model: "github.com/vektah/gqlgen/codegen/testdata.Shape"}, - "ShapeUnion": {Model: "github.com/vektah/gqlgen/codegen/testdata.ShapeUnion"}, - "Circle": {Model: "github.com/vektah/gqlgen/codegen/testdata.Circle"}, - "Rectangle": {Model: "github.com/vektah/gqlgen/codegen/testdata.Rectangle"}, + "Shape": {Model: "github.com/vektah/gqlgen/codegen/tests.Shape"}, + "ShapeUnion": {Model: "github.com/vektah/gqlgen/codegen/tests.ShapeUnion"}, + "Circle": {Model: "github.com/vektah/gqlgen/codegen/tests.Circle"}, + "Rectangle": {Model: "github.com/vektah/gqlgen/codegen/tests.Rectangle"}, }) require.NoError(t, err) @@ -39,8 +39,8 @@ func TestShapes(t *testing.T) { func generate(name string, schema string, typemap ...TypeMap) error { cfg := Config{ SchemaStr: schema, - Exec: PackageConfig{Filename: "testdata/gen/" + name + "/exec.go"}, - Model: PackageConfig{Filename: "testdata/gen/" + name + "/model.go"}, + Exec: PackageConfig{Filename: "tests/gen/" + name + "/exec.go"}, + Model: PackageConfig{Filename: "tests/gen/" + name + "/model.go"}, } if len(typemap) > 0 { cfg.Models = typemap[0] @@ -48,7 +48,7 @@ func generate(name string, schema string, typemap ...TypeMap) error { err := Generate(cfg) if err == nil { conf := loader.Config{} - conf.Import("github.com/vektah/gqlgen/codegen/testdata/gen/" + name) + conf.Import("github.com/vektah/gqlgen/codegen/tests/gen/" + name) _, err = conf.Load() if err != nil { diff --git a/codegen/models_build.go b/codegen/models_build.go index 211d4bd4aa2..80132a8f77b 100644 --- a/codegen/models_build.go +++ b/codegen/models_build.go @@ -4,7 +4,7 @@ import ( "sort" "strings" - "github.com/vektah/gqlgen/neelance/schema" + "github.com/vektah/gqlparser/ast" "golang.org/x/tools/go/loader" ) @@ -13,8 +13,8 @@ func (cfg *Config) buildModels(types NamedTypes, prog *loader.Program) ([]Model, for _, typ := range cfg.schema.Types { var model Model - switch typ := typ.(type) { - case *schema.Object: + switch typ.Kind { + case ast.Object: obj, err := cfg.buildObject(types, typ) if err != nil { return nil, err @@ -23,7 +23,7 @@ func (cfg *Config) buildModels(types NamedTypes, prog *loader.Program) ([]Model, continue } model = cfg.obj2Model(obj) - case *schema.InputObject: + case ast.InputObject: obj, err := buildInput(types, typ) if err != nil { return nil, err @@ -32,7 +32,7 @@ func (cfg *Config) buildModels(types NamedTypes, prog *loader.Program) ([]Model, continue } model = cfg.obj2Model(obj) - case *schema.Interface, *schema.Union: + case ast.Interface, ast.Union: intf := cfg.buildInterface(types, typ, prog) if intf.IsUserDefined { continue diff --git a/codegen/object_build.go b/codegen/object_build.go index 0ef40feff21..d0d6e34fe50 100644 --- a/codegen/object_build.go +++ b/codegen/object_build.go @@ -6,7 +6,7 @@ import ( "strings" "github.com/pkg/errors" - "github.com/vektah/gqlgen/neelance/schema" + "github.com/vektah/gqlparser/ast" "golang.org/x/tools/go/loader" ) @@ -14,26 +14,27 @@ func (cfg *Config) buildObjects(types NamedTypes, prog *loader.Program, imports var objects Objects for _, typ := range cfg.schema.Types { - switch typ := typ.(type) { - case *schema.Object: - obj, err := cfg.buildObject(types, typ) - if err != nil { - return nil, err - } + if typ.Kind != ast.Object { + continue + } - def, err := findGoType(prog, obj.Package, obj.GoType) - if err != nil { - return nil, err - } - if def != nil { - for _, bindErr := range bindObject(def.Type(), obj, imports) { - log.Println(bindErr.Error()) - log.Println(" Adding resolver method") - } - } + obj, err := cfg.buildObject(types, typ) + if err != nil { + return nil, err + } - objects = append(objects, obj) + def, err := findGoType(prog, obj.Package, obj.GoType) + if err != nil { + return nil, err } + if def != nil { + for _, bindErr := range bindObject(def.Type(), obj, imports) { + log.Println(bindErr.Error()) + log.Println(" Adding resolver method") + } + } + + objects = append(objects, obj) } sort.Slice(objects, func(i, j int) bool { @@ -80,15 +81,50 @@ func sanitizeGoName(name string) string { return name } -func (cfg *Config) buildObject(types NamedTypes, typ *schema.Object) (*Object, error) { - obj := &Object{NamedType: types[typ.TypeName()]} - typeEntry, entryExists := cfg.Models[typ.TypeName()] +func (cfg *Config) buildObject(types NamedTypes, typ *ast.Definition) (*Object, error) { + obj := &Object{NamedType: types[typ.Name]} + typeEntry, entryExists := cfg.Models[typ.Name] + + if typ == cfg.schema.Query { + obj.Root = true + } + + if typ == cfg.schema.Mutation { + obj.Root = true + obj.DisableConcurrency = true + } - for _, i := range typ.Interfaces { - obj.Satisfies = append(obj.Satisfies, i.Name) + if typ == cfg.schema.Subscription { + obj.Root = true + obj.Stream = true } + obj.Satisfies = append(obj.Satisfies, typ.Interfaces...) + for _, field := range typ.Fields { + if typ == cfg.schema.Query && field.Name == "__type" { + obj.Fields = append(obj.Fields, Field{ + Type: &Type{types["__Schema"], []string{modPtr}, nil}, + GQLName: "__schema", + NoErr: true, + GoMethodName: "ec.introspectSchema", + Object: obj, + }) + continue + } + if typ == cfg.schema.Query && field.Name == "__schema" { + obj.Fields = append(obj.Fields, Field{ + Type: &Type{types["__Type"], []string{modPtr}, nil}, + GQLName: "__type", + NoErr: true, + GoMethodName: "ec.introspectType", + Args: []FieldArgument{ + {GQLName: "name", Type: &Type{types["String"], []string{}, nil}, Object: &Object{}}, + }, + Object: obj, + }) + continue + } var forceResolver bool if entryExists { @@ -98,20 +134,24 @@ func (cfg *Config) buildObject(types NamedTypes, typ *schema.Object) (*Object, e } var args []FieldArgument - for _, arg := range field.Args { + for _, arg := range field.Arguments { newArg := FieldArgument{ - GQLName: arg.Name.Name, + GQLName: arg.Name, Type: types.getType(arg.Type), Object: obj, - GoVarName: sanitizeGoName(arg.Name.Name), + GoVarName: sanitizeGoName(arg.Name), } if !newArg.Type.IsInput && !newArg.Type.IsScalar { return nil, errors.Errorf("%s cannot be used as argument of %s.%s. only input and scalar types are allowed", arg.Type, obj.GQLType, field.Name) } - if arg.Default != nil { - newArg.Default = arg.Default.Value(nil) + if arg.DefaultValue != nil { + var err error + newArg.Default, err = arg.DefaultValue.Value(nil) + if err != nil { + return nil, errors.Errorf("default value for %s.%s is not valid: %s", typ.Name, field.Name, err.Error()) + } newArg.StripPtr() } args = append(args, newArg) @@ -126,19 +166,5 @@ func (cfg *Config) buildObject(types NamedTypes, typ *schema.Object) (*Object, e }) } - for name, typ := range cfg.schema.EntryPoints { - schemaObj := typ.(*schema.Object) - if schemaObj.TypeName() != obj.GQLType { - continue - } - - obj.Root = true - if name == "mutation" { - obj.DisableConcurrency = true - } - if name == "subscription" { - obj.Stream = true - } - } return obj, nil } diff --git a/codegen/templates/data.go b/codegen/templates/data.go index d6da480770b..80c2c989882 100644 --- a/codegen/templates/data.go +++ b/codegen/templates/data.go @@ -3,9 +3,9 @@ package templates var data = map[string]string{ "args.gotpl": "\t{{- if . }}args := map[string]interface{}{} {{end}}\n\t{{- range $i, $arg := . }}\n\t\tvar arg{{$i}} {{$arg.Signature }}\n\t\tif tmp, ok := field.Args[{{$arg.GQLName|quote}}]; ok {\n\t\t\tvar err error\n\t\t\t{{$arg.Unmarshal (print \"arg\" $i) \"tmp\" }}\n\t\t\tif err != nil {\n\t\t\t\tec.Error(ctx, err)\n\t\t\t\t{{- if $arg.Object.Stream }}\n\t\t\t\t\treturn nil\n\t\t\t\t{{- else }}\n\t\t\t\t\treturn graphql.Null\n\t\t\t\t{{- end }}\n\t\t\t}\n\t\t} {{ if $arg.Default }} else {\n\t\t\tvar tmp interface{} = {{ $arg.Default | dump }}\n\t\t\tvar err error\n\t\t\t{{$arg.Unmarshal (print \"arg\" $i) \"tmp\" }}\n\t\t\tif err != nil {\n\t\t\t\tec.Error(ctx, err)\n\t\t\t\t{{- if $arg.Object.Stream }}\n\t\t\t\t\treturn nil\n\t\t\t\t{{- else }}\n\t\t\t\t\treturn graphql.Null\n\t\t\t\t{{- end }}\n\t\t\t}\n\t\t}\n\t\t{{end }}\n\t\targs[{{$arg.GQLName|quote}}] = arg{{$i}}\n\t{{- end -}}\n", "field.gotpl": "{{ $field := . }}\n{{ $object := $field.Object }}\n\n{{- if $object.Stream }}\n\tfunc (ec *executionContext) _{{$object.GQLType}}_{{$field.GQLName}}(ctx context.Context, field graphql.CollectedField) func() graphql.Marshaler {\n\t\t{{- template \"args.gotpl\" $field.Args }}\n\t\tctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{Field: field})\n\t\tresults, err := ec.resolvers.{{ $object.GQLType }}_{{ $field.GQLName }}({{ $field.CallArgs }})\n\t\tif err != nil {\n\t\t\tec.Error(ctx, err)\n\t\t\treturn nil\n\t\t}\n\t\treturn func() graphql.Marshaler {\n\t\t\tres, ok := <-results\n\t\t\tif !ok {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tvar out graphql.OrderedMap\n\t\t\tout.Add(field.Alias, func() graphql.Marshaler { {{ $field.WriteJson }} }())\n\t\t\treturn &out\n\t\t}\n\t}\n{{ else }}\n\tfunc (ec *executionContext) _{{$object.GQLType}}_{{$field.GQLName}}(ctx context.Context, field graphql.CollectedField, {{if not $object.Root}}obj *{{$object.FullName}}{{end}}) graphql.Marshaler {\n\t\t{{- template \"args.gotpl\" $field.Args }}\n\n\t\t{{- if $field.IsConcurrent }}\n\t\t\tctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{\n\t\t\t\tObject: {{$object.GQLType|quote}},\n\t\t\t\tArgs: {{if $field.Args }}args{{else}}nil{{end}},\n\t\t\t\tField: field,\n\t\t\t})\n\t\t\treturn graphql.Defer(func() (ret graphql.Marshaler) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\tuserErr := ec.Recover(ctx, r)\n\t\t\t\t\t\tec.Error(ctx, userErr)\n\t\t\t\t\t\tret = graphql.Null\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t{{ else }}\n\t\t\trctx := graphql.GetResolverContext(ctx)\n\t\t\trctx.Object = {{$object.GQLType|quote}}\n\t\t\trctx.Args = {{if $field.Args }}args{{else}}nil{{end}}\n\t\t\trctx.Field = field\n\t\t\trctx.PushField(field.Alias)\n\t\t\tdefer rctx.Pop()\n\t\t{{- end }}\n\n\t\t\t{{- if $field.IsResolver }}\n\t\t\t\tresTmp, err := ec.ResolverMiddleware(ctx, func(ctx context.Context) (interface{}, error) {\n\t\t\t\t\treturn ec.resolvers.{{ $object.GQLType }}_{{ $field.GQLName }}({{ $field.CallArgs }})\n\t\t\t\t})\n\t\t\t\tif err != nil {\n\t\t\t\t\tec.Error(ctx, err)\n\t\t\t\t\treturn graphql.Null\n\t\t\t\t}\n\t\t\t\tif resTmp == nil {\n\t\t\t\t\treturn graphql.Null\n\t\t\t\t}\n\t\t\t\tres := resTmp.({{$field.Signature}})\n\t\t\t{{- else if $field.GoVarName }}\n\t\t\t\tres := obj.{{$field.GoVarName}}\n\t\t\t{{- else if $field.GoMethodName }}\n\t\t\t\t{{- if $field.NoErr }}\n\t\t\t\t\tres := {{$field.GoMethodName}}({{ $field.CallArgs }})\n\t\t\t\t{{- else }}\n\t\t\t\t\tres, err := {{$field.GoMethodName}}({{ $field.CallArgs }})\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tec.Error(ctx, err)\n\t\t\t\t\t\treturn graphql.Null\n\t\t\t\t\t}\n\t\t\t\t{{- end }}\n\t\t\t{{- end }}\n\t\t\t{{ $field.WriteJson }}\n\t\t{{- if $field.IsConcurrent }}\n\t\t\t})\n\t\t{{- end }}\n\t}\n{{ end }}\n", - "generated.gotpl": "// Code generated by github.com/vektah/gqlgen, DO NOT EDIT.\n\npackage {{ .PackageName }}\n\nimport (\n{{- range $import := .Imports }}\n\t{{- $import.Write }}\n{{ end }}\n)\n\n// MakeExecutableSchema creates an ExecutableSchema from the Resolvers interface.\nfunc MakeExecutableSchema(resolvers Resolvers) graphql.ExecutableSchema {\n\treturn &executableSchema{resolvers: resolvers}\n}\n\n// NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface.\nfunc NewExecutableSchema(resolvers ResolverRoot) graphql.ExecutableSchema {\n\treturn MakeExecutableSchema(shortMapper{r: resolvers})\n}\n\ntype Resolvers interface {\n{{- range $object := .Objects -}}\n\t{{ range $field := $object.Fields -}}\n\t\t{{ $field.ResolverDeclaration }}\n\t{{ end }}\n{{- end }}\n}\n\ntype ResolverRoot interface {\n{{- range $object := .Objects -}}\n\t{{ if $object.HasResolvers -}}\n\t\t{{$object.GQLType}}() {{$object.GQLType}}Resolver\n\t{{ end }}\n{{- end }}\n}\n\n{{- range $object := .Objects -}}\n\t{{ if $object.HasResolvers }}\n\t\ttype {{$object.GQLType}}Resolver interface {\n\t\t{{ range $field := $object.Fields -}}\n\t\t\t{{ $field.ShortResolverDeclaration }}\n\t\t{{ end }}\n\t\t}\n\t{{- end }}\n{{- end }}\n\ntype shortMapper struct {\n\tr ResolverRoot\n}\n\n{{- range $object := .Objects -}}\n\t{{ range $field := $object.Fields -}}\n\t\t{{- if $field.IsResolver }}\n\t\t\tfunc (s shortMapper) {{ $field.ResolverDeclaration }} {\n\t\t\t\treturn s.r.{{$field.ShortInvocation}}\n\t\t\t}\n\t\t{{- end }}\n\t{{ end }}\n{{- end }}\n\ntype executableSchema struct {\n\tresolvers Resolvers\n}\n\nfunc (e *executableSchema) Schema() *schema.Schema {\n\treturn parsedSchema\n}\n\nfunc (e *executableSchema) Query(ctx context.Context, op *query.Operation) *graphql.Response {\n\t{{- if .QueryRoot }}\n\t\tec := executionContext{graphql.GetRequestContext(ctx), e.resolvers}\n\n\t\tbuf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {\n\t\t\tdata := ec._{{.QueryRoot.GQLType}}(ctx, op.Selections)\n\t\t\tvar buf bytes.Buffer\n\t\t\tdata.MarshalGQL(&buf)\n\t\t\treturn buf.Bytes()\n\t\t})\n\n\t\treturn &graphql.Response{\n\t\t\tData: buf,\n\t\t\tErrors: ec.Errors,\n\t\t}\n\t{{- else }}\n\t\treturn graphql.ErrorResponse(ctx, \"queries are not supported\")\n\t{{- end }}\n}\n\nfunc (e *executableSchema) Mutation(ctx context.Context, op *query.Operation) *graphql.Response {\n\t{{- if .MutationRoot }}\n\t\tec := executionContext{graphql.GetRequestContext(ctx), e.resolvers}\n\n\t\tbuf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {\n\t\t\tdata := ec._{{.MutationRoot.GQLType}}(ctx, op.Selections)\n\t\t\tvar buf bytes.Buffer\n\t\t\tdata.MarshalGQL(&buf)\n\t\t\treturn buf.Bytes()\n\t\t})\n\n\t\treturn &graphql.Response{\n\t\t\tData: buf,\n\t\t\tErrors: ec.Errors,\n\t\t}\n\t{{- else }}\n\t\treturn graphql.ErrorResponse(ctx, \"mutations are not supported\")\n\t{{- end }}\n}\n\nfunc (e *executableSchema) Subscription(ctx context.Context, op *query.Operation) func() *graphql.Response {\n\t{{- if .SubscriptionRoot }}\n\t\tec := executionContext{graphql.GetRequestContext(ctx), e.resolvers}\n\n\t\tnext := ec._{{.SubscriptionRoot.GQLType}}(ctx, op.Selections)\n\t\tif ec.Errors != nil {\n\t\t\treturn graphql.OneShot(&graphql.Response{Data: []byte(\"null\"), Errors: ec.Errors})\n\t\t}\n\n\t\tvar buf bytes.Buffer\n\t\treturn func() *graphql.Response {\n\t\t\tbuf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {\n\t\t\t\tbuf.Reset()\n\t\t\t\tdata := next()\n\n\t\t\t\tif data == nil {\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\t\t\t\tdata.MarshalGQL(&buf)\n\t\t\t\treturn buf.Bytes()\n\t\t\t})\n\n\t\t\treturn &graphql.Response{\n\t\t\t\tData: buf,\n\t\t\t\tErrors: ec.Errors,\n\t\t\t}\n\t\t}\n\t{{- else }}\n\t\treturn graphql.OneShot(graphql.ErrorResponse(ctx, \"subscriptions are not supported\"))\n\t{{- end }}\n}\n\ntype executionContext struct {\n\t*graphql.RequestContext\n\n\tresolvers Resolvers\n}\n\n{{- range $object := .Objects }}\n\t{{ template \"object.gotpl\" $object }}\n\n\t{{- range $field := $object.Fields }}\n\t\t{{ template \"field.gotpl\" $field }}\n\t{{ end }}\n{{- end}}\n\n{{- range $interface := .Interfaces }}\n\t{{ template \"interface.gotpl\" $interface }}\n{{- end }}\n\n{{- range $input := .Inputs }}\n\t{{ template \"input.gotpl\" $input }}\n{{- end }}\n\nfunc (ec *executionContext) introspectSchema() *introspection.Schema {\n\treturn introspection.WrapSchema(parsedSchema)\n}\n\nfunc (ec *executionContext) introspectType(name string) *introspection.Type {\n\tt := parsedSchema.Resolve(name)\n\tif t == nil {\n\t\treturn nil\n\t}\n\treturn introspection.WrapType(t)\n}\n\nvar parsedSchema = schema.MustParse({{.SchemaRaw|rawQuote}})\n", + "generated.gotpl": "// Code generated by github.com/vektah/gqlgen, DO NOT EDIT.\n\npackage {{ .PackageName }}\n\nimport (\n{{- range $import := .Imports }}\n\t{{- $import.Write }}\n{{ end }}\n)\n\n// MakeExecutableSchema creates an ExecutableSchema from the Resolvers interface.\nfunc MakeExecutableSchema(resolvers Resolvers) graphql.ExecutableSchema {\n\treturn &executableSchema{resolvers: resolvers}\n}\n\n// NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface.\nfunc NewExecutableSchema(resolvers ResolverRoot) graphql.ExecutableSchema {\n\treturn MakeExecutableSchema(shortMapper{r: resolvers})\n}\n\ntype Resolvers interface {\n{{- range $object := .Objects -}}\n\t{{ range $field := $object.Fields -}}\n\t\t{{ $field.ResolverDeclaration }}\n\t{{ end }}\n{{- end }}\n}\n\ntype ResolverRoot interface {\n{{- range $object := .Objects -}}\n\t{{ if $object.HasResolvers -}}\n\t\t{{$object.GQLType}}() {{$object.GQLType}}Resolver\n\t{{ end }}\n{{- end }}\n}\n\n{{- range $object := .Objects -}}\n\t{{ if $object.HasResolvers }}\n\t\ttype {{$object.GQLType}}Resolver interface {\n\t\t{{ range $field := $object.Fields -}}\n\t\t\t{{ $field.ShortResolverDeclaration }}\n\t\t{{ end }}\n\t\t}\n\t{{- end }}\n{{- end }}\n\ntype shortMapper struct {\n\tr ResolverRoot\n}\n\n{{- range $object := .Objects -}}\n\t{{ range $field := $object.Fields -}}\n\t\t{{- if $field.IsResolver }}\n\t\t\tfunc (s shortMapper) {{ $field.ResolverDeclaration }} {\n\t\t\t\treturn s.r.{{$field.ShortInvocation}}\n\t\t\t}\n\t\t{{- end }}\n\t{{ end }}\n{{- end }}\n\ntype executableSchema struct {\n\tresolvers Resolvers\n}\n\nfunc (e *executableSchema) Schema() *ast.Schema {\n\treturn parsedSchema\n}\n\nfunc (e *executableSchema) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response {\n\t{{- if .QueryRoot }}\n\t\tec := executionContext{graphql.GetRequestContext(ctx), e.resolvers}\n\n\t\tbuf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {\n\t\t\tdata := ec._{{.QueryRoot.GQLType}}(ctx, op.SelectionSet)\n\t\t\tvar buf bytes.Buffer\n\t\t\tdata.MarshalGQL(&buf)\n\t\t\treturn buf.Bytes()\n\t\t})\n\n\t\treturn &graphql.Response{\n\t\t\tData: buf,\n\t\t\tErrors: ec.Errors,\n\t\t}\n\t{{- else }}\n\t\treturn graphql.ErrorResponse(ctx, \"queries are not supported\")\n\t{{- end }}\n}\n\nfunc (e *executableSchema) Mutation(ctx context.Context, op *ast.OperationDefinition) *graphql.Response {\n\t{{- if .MutationRoot }}\n\t\tec := executionContext{graphql.GetRequestContext(ctx), e.resolvers}\n\n\t\tbuf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {\n\t\t\tdata := ec._{{.MutationRoot.GQLType}}(ctx, op.SelectionSet)\n\t\t\tvar buf bytes.Buffer\n\t\t\tdata.MarshalGQL(&buf)\n\t\t\treturn buf.Bytes()\n\t\t})\n\n\t\treturn &graphql.Response{\n\t\t\tData: buf,\n\t\t\tErrors: ec.Errors,\n\t\t}\n\t{{- else }}\n\t\treturn graphql.ErrorResponse(ctx, \"mutations are not supported\")\n\t{{- end }}\n}\n\nfunc (e *executableSchema) Subscription(ctx context.Context, op *ast.OperationDefinition) func() *graphql.Response {\n\t{{- if .SubscriptionRoot }}\n\t\tec := executionContext{graphql.GetRequestContext(ctx), e.resolvers}\n\n\t\tnext := ec._{{.SubscriptionRoot.GQLType}}(ctx, op.SelectionSet)\n\t\tif ec.Errors != nil {\n\t\t\treturn graphql.OneShot(&graphql.Response{Data: []byte(\"null\"), Errors: ec.Errors})\n\t\t}\n\n\t\tvar buf bytes.Buffer\n\t\treturn func() *graphql.Response {\n\t\t\tbuf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {\n\t\t\t\tbuf.Reset()\n\t\t\t\tdata := next()\n\n\t\t\t\tif data == nil {\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\t\t\t\tdata.MarshalGQL(&buf)\n\t\t\t\treturn buf.Bytes()\n\t\t\t})\n\n\t\t\treturn &graphql.Response{\n\t\t\t\tData: buf,\n\t\t\t\tErrors: ec.Errors,\n\t\t\t}\n\t\t}\n\t{{- else }}\n\t\treturn graphql.OneShot(graphql.ErrorResponse(ctx, \"subscriptions are not supported\"))\n\t{{- end }}\n}\n\ntype executionContext struct {\n\t*graphql.RequestContext\n\n\tresolvers Resolvers\n}\n\n{{- range $object := .Objects }}\n\t{{ template \"object.gotpl\" $object }}\n\n\t{{- range $field := $object.Fields }}\n\t\t{{ template \"field.gotpl\" $field }}\n\t{{ end }}\n{{- end}}\n\n{{- range $interface := .Interfaces }}\n\t{{ template \"interface.gotpl\" $interface }}\n{{- end }}\n\n{{- range $input := .Inputs }}\n\t{{ template \"input.gotpl\" $input }}\n{{- end }}\n\nfunc (ec *executionContext) introspectSchema() *introspection.Schema {\n\treturn introspection.WrapSchema(parsedSchema)\n}\n\nfunc (ec *executionContext) introspectType(name string) *introspection.Type {\n\treturn introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name])\n}\n\nvar parsedSchema = gqlparser.MustLoadSchema(introspection.Prelude + {{.SchemaRaw|rawQuote}})\n", "input.gotpl": "\t{{- if .IsMarshaled }}\n\tfunc Unmarshal{{ .GQLType }}(v interface{}) ({{.FullName}}, error) {\n\t\tvar it {{.FullName}}\n\t\tvar asMap = v.(map[string]interface{})\n\t\t{{ range $field := .Fields}}\n\t\t\t{{- if $field.Default}}\n\t\t\t\tif _, present := asMap[{{$field.GQLName|quote}}] ; !present {\n\t\t\t\t\tasMap[{{$field.GQLName|quote}}] = {{ $field.Default | dump }}\n\t\t\t\t}\n\t\t\t{{- end}}\n\t\t{{- end }}\n\n\t\tfor k, v := range asMap {\n\t\t\tswitch k {\n\t\t\t{{- range $field := .Fields }}\n\t\t\tcase {{$field.GQLName|quote}}:\n\t\t\t\tvar err error\n\t\t\t\t{{ $field.Unmarshal (print \"it.\" $field.GoVarName) \"v\" }}\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn it, err\n\t\t\t\t}\n\t\t\t{{- end }}\n\t\t\t}\n\t\t}\n\n\t\treturn it, nil\n\t}\n\t{{- end }}\n", - "interface.gotpl": "{{- $interface := . }}\n\nfunc (ec *executionContext) _{{$interface.GQLType}}(ctx context.Context, sel []query.Selection, obj *{{$interface.FullName}}) graphql.Marshaler {\n\tswitch obj := (*obj).(type) {\n\tcase nil:\n\t\treturn graphql.Null\n\t{{- range $implementor := $interface.Implementors }}\n\t\t{{- if $implementor.ValueReceiver }}\n\t\t\tcase {{$implementor.FullName}}:\n\t\t\t\treturn ec._{{$implementor.GQLType}}(ctx, sel, &obj)\n\t\t{{- end}}\n\t\tcase *{{$implementor.FullName}}:\n\t\t\treturn ec._{{$implementor.GQLType}}(ctx, sel, obj)\n\t{{- end }}\n\tdefault:\n\t\tpanic(fmt.Errorf(\"unexpected type %T\", obj))\n\t}\n}\n", + "interface.gotpl": "{{- $interface := . }}\n\nfunc (ec *executionContext) _{{$interface.GQLType}}(ctx context.Context, sel ast.SelectionSet, obj *{{$interface.FullName}}) graphql.Marshaler {\n\tswitch obj := (*obj).(type) {\n\tcase nil:\n\t\treturn graphql.Null\n\t{{- range $implementor := $interface.Implementors }}\n\t\t{{- if $implementor.ValueReceiver }}\n\t\t\tcase {{$implementor.FullName}}:\n\t\t\t\treturn ec._{{$implementor.GQLType}}(ctx, sel, &obj)\n\t\t{{- end}}\n\t\tcase *{{$implementor.FullName}}:\n\t\t\treturn ec._{{$implementor.GQLType}}(ctx, sel, obj)\n\t{{- end }}\n\tdefault:\n\t\tpanic(fmt.Errorf(\"unexpected type %T\", obj))\n\t}\n}\n", "models.gotpl": "// Code generated by github.com/vektah/gqlgen, DO NOT EDIT.\n\npackage {{ .PackageName }}\n\nimport (\n{{- range $import := .Imports }}\n\t{{- $import.Write }}\n{{ end }}\n)\n\n{{ range $model := .Models }}\n\t{{- if .IsInterface }}\n\t\ttype {{.GoType}} interface {}\n\t{{- else }}\n\t\ttype {{.GoType}} struct {\n\t\t\t{{- range $field := .Fields }}\n\t\t\t\t{{- if $field.GoVarName }}\n\t\t\t\t\t{{ $field.GoVarName }} {{$field.Signature}} `json:\"{{$field.GQLName}}\"`\n\t\t\t\t{{- else }}\n\t\t\t\t\t{{ $field.GoFKName }} {{$field.GoFKType}}\n\t\t\t\t{{- end }}\n\t\t\t{{- end }}\n\t\t}\n\t{{- end }}\n{{- end}}\n\n{{ range $enum := .Enums }}\n\ttype {{.GoType}} string\n\tconst (\n\t{{ range $value := .Values -}}\n\t\t{{with .Description}} {{.|prefixLines \"// \"}} {{end}}\n\t\t{{$enum.GoType}}{{ .Name|toCamel }} {{$enum.GoType}} = {{.Name|quote}}\n\t{{- end }}\n\t)\n\n\tfunc (e {{.GoType}}) IsValid() bool {\n\t\tswitch e {\n\t\tcase {{ range $index, $element := .Values}}{{if $index}},{{end}}{{ $enum.GoType }}{{ $element.Name|toCamel }}{{end}}:\n\t\t\treturn true\n\t\t}\n\t\treturn false\n\t}\n\n\tfunc (e {{.GoType}}) String() string {\n\t\treturn string(e)\n\t}\n\n\tfunc (e *{{.GoType}}) UnmarshalGQL(v interface{}) error {\n\t\tstr, ok := v.(string)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"enums must be strings\")\n\t\t}\n\n\t\t*e = {{.GoType}}(str)\n\t\tif !e.IsValid() {\n\t\t\treturn fmt.Errorf(\"%s is not a valid {{.GQLType}}\", str)\n\t\t}\n\t\treturn nil\n\t}\n\n\tfunc (e {{.GoType}}) MarshalGQL(w io.Writer) {\n\t\tfmt.Fprint(w, strconv.Quote(e.String()))\n\t}\n\n{{- end }}\n", - "object.gotpl": "{{ $object := . }}\n\nvar {{ $object.GQLType|lcFirst}}Implementors = {{$object.Implementors}}\n\n// nolint: gocyclo, errcheck, gas, goconst\n{{- if .Stream }}\nfunc (ec *executionContext) _{{$object.GQLType}}(ctx context.Context, sel []query.Selection) func() graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.Doc, sel, {{$object.GQLType|lcFirst}}Implementors, ec.Variables)\n\tctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{\n\t\tObject: {{$object.GQLType|quote}},\n\t})\n\tif len(fields) != 1 {\n\t\tec.Errorf(ctx, \"must subscribe to exactly one stream\")\n\t\treturn nil\n\t}\n\n\tswitch fields[0].Name {\n\t{{- range $field := $object.Fields }}\n\tcase \"{{$field.GQLName}}\":\n\t\treturn ec._{{$object.GQLType}}_{{$field.GQLName}}(ctx, fields[0])\n\t{{- end }}\n\tdefault:\n\t\tpanic(\"unknown field \" + strconv.Quote(fields[0].Name))\n\t}\n}\n{{- else }}\nfunc (ec *executionContext) _{{$object.GQLType}}(ctx context.Context, sel []query.Selection{{if not $object.Root}}, obj *{{$object.FullName}} {{end}}) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.Doc, sel, {{$object.GQLType|lcFirst}}Implementors, ec.Variables)\n\t{{if $object.Root}}\n\t\tctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{\n\t\t\tObject: {{$object.GQLType|quote}},\n\t\t})\n\t{{end}}\n\tout := graphql.NewOrderedMap(len(fields))\n\tfor i, field := range fields {\n\t\tout.Keys[i] = field.Alias\n\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString({{$object.GQLType|quote}})\n\t\t{{- range $field := $object.Fields }}\n\t\tcase \"{{$field.GQLName}}\":\n\t\t\tout.Values[i] = ec._{{$object.GQLType}}_{{$field.GQLName}}(ctx, field{{if not $object.Root}}, obj{{end}})\n\t\t{{- end }}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\n\treturn out\n}\n{{- end }}\n", + "object.gotpl": "{{ $object := . }}\n\nvar {{ $object.GQLType|lcFirst}}Implementors = {{$object.Implementors}}\n\n// nolint: gocyclo, errcheck, gas, goconst\n{{- if .Stream }}\nfunc (ec *executionContext) _{{$object.GQLType}}(ctx context.Context, sel ast.SelectionSet) func() graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.Doc, sel, {{$object.GQLType|lcFirst}}Implementors, ec.Variables)\n\tctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{\n\t\tObject: {{$object.GQLType|quote}},\n\t})\n\tif len(fields) != 1 {\n\t\tec.Errorf(ctx, \"must subscribe to exactly one stream\")\n\t\treturn nil\n\t}\n\n\tswitch fields[0].Name {\n\t{{- range $field := $object.Fields }}\n\tcase \"{{$field.GQLName}}\":\n\t\treturn ec._{{$object.GQLType}}_{{$field.GQLName}}(ctx, fields[0])\n\t{{- end }}\n\tdefault:\n\t\tpanic(\"unknown field \" + strconv.Quote(fields[0].Name))\n\t}\n}\n{{- else }}\nfunc (ec *executionContext) _{{$object.GQLType}}(ctx context.Context, sel ast.SelectionSet{{if not $object.Root}}, obj *{{$object.FullName}} {{end}}) graphql.Marshaler {\n\tfields := graphql.CollectFields(ec.Doc, sel, {{$object.GQLType|lcFirst}}Implementors, ec.Variables)\n\t{{if $object.Root}}\n\t\tctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{\n\t\t\tObject: {{$object.GQLType|quote}},\n\t\t})\n\t{{end}}\n\tout := graphql.NewOrderedMap(len(fields))\n\tfor i, field := range fields {\n\t\tout.Keys[i] = field.Alias\n\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString({{$object.GQLType|quote}})\n\t\t{{- range $field := $object.Fields }}\n\t\tcase \"{{$field.GQLName}}\":\n\t\t\tout.Values[i] = ec._{{$object.GQLType}}_{{$field.GQLName}}(ctx, field{{if not $object.Root}}, obj{{end}})\n\t\t{{- end }}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\n\treturn out\n}\n{{- end }}\n", } diff --git a/codegen/templates/generated.gotpl b/codegen/templates/generated.gotpl index cc1dc459b07..523234c6327 100644 --- a/codegen/templates/generated.gotpl +++ b/codegen/templates/generated.gotpl @@ -62,16 +62,16 @@ type executableSchema struct { resolvers Resolvers } -func (e *executableSchema) Schema() *schema.Schema { +func (e *executableSchema) Schema() *ast.Schema { return parsedSchema } -func (e *executableSchema) Query(ctx context.Context, op *query.Operation) *graphql.Response { +func (e *executableSchema) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { {{- if .QueryRoot }} ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers} buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte { - data := ec._{{.QueryRoot.GQLType}}(ctx, op.Selections) + data := ec._{{.QueryRoot.GQLType}}(ctx, op.SelectionSet) var buf bytes.Buffer data.MarshalGQL(&buf) return buf.Bytes() @@ -86,12 +86,12 @@ func (e *executableSchema) Query(ctx context.Context, op *query.Operation) *grap {{- end }} } -func (e *executableSchema) Mutation(ctx context.Context, op *query.Operation) *graphql.Response { +func (e *executableSchema) Mutation(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { {{- if .MutationRoot }} ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers} buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte { - data := ec._{{.MutationRoot.GQLType}}(ctx, op.Selections) + data := ec._{{.MutationRoot.GQLType}}(ctx, op.SelectionSet) var buf bytes.Buffer data.MarshalGQL(&buf) return buf.Bytes() @@ -106,11 +106,11 @@ func (e *executableSchema) Mutation(ctx context.Context, op *query.Operation) *g {{- end }} } -func (e *executableSchema) Subscription(ctx context.Context, op *query.Operation) func() *graphql.Response { +func (e *executableSchema) Subscription(ctx context.Context, op *ast.OperationDefinition) func() *graphql.Response { {{- if .SubscriptionRoot }} ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers} - next := ec._{{.SubscriptionRoot.GQLType}}(ctx, op.Selections) + next := ec._{{.SubscriptionRoot.GQLType}}(ctx, op.SelectionSet) if ec.Errors != nil { return graphql.OneShot(&graphql.Response{Data: []byte("null"), Errors: ec.Errors}) } @@ -165,11 +165,7 @@ func (ec *executionContext) introspectSchema() *introspection.Schema { } func (ec *executionContext) introspectType(name string) *introspection.Type { - t := parsedSchema.Resolve(name) - if t == nil { - return nil - } - return introspection.WrapType(t) + return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]) } -var parsedSchema = schema.MustParse({{.SchemaRaw|rawQuote}}) +var parsedSchema = gqlparser.MustLoadSchema(introspection.Prelude + {{.SchemaRaw|rawQuote}}) diff --git a/codegen/templates/interface.gotpl b/codegen/templates/interface.gotpl index 817d0abe540..84cbe5002c5 100644 --- a/codegen/templates/interface.gotpl +++ b/codegen/templates/interface.gotpl @@ -1,6 +1,6 @@ {{- $interface := . }} -func (ec *executionContext) _{{$interface.GQLType}}(ctx context.Context, sel []query.Selection, obj *{{$interface.FullName}}) graphql.Marshaler { +func (ec *executionContext) _{{$interface.GQLType}}(ctx context.Context, sel ast.SelectionSet, obj *{{$interface.FullName}}) graphql.Marshaler { switch obj := (*obj).(type) { case nil: return graphql.Null diff --git a/codegen/templates/object.gotpl b/codegen/templates/object.gotpl index b531d5fe6d0..31a563c195c 100644 --- a/codegen/templates/object.gotpl +++ b/codegen/templates/object.gotpl @@ -4,7 +4,7 @@ var {{ $object.GQLType|lcFirst}}Implementors = {{$object.Implementors}} // nolint: gocyclo, errcheck, gas, goconst {{- if .Stream }} -func (ec *executionContext) _{{$object.GQLType}}(ctx context.Context, sel []query.Selection) func() graphql.Marshaler { +func (ec *executionContext) _{{$object.GQLType}}(ctx context.Context, sel ast.SelectionSet) func() graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, {{$object.GQLType|lcFirst}}Implementors, ec.Variables) ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{ Object: {{$object.GQLType|quote}}, @@ -24,7 +24,7 @@ func (ec *executionContext) _{{$object.GQLType}}(ctx context.Context, sel []quer } } {{- else }} -func (ec *executionContext) _{{$object.GQLType}}(ctx context.Context, sel []query.Selection{{if not $object.Root}}, obj *{{$object.FullName}} {{end}}) graphql.Marshaler { +func (ec *executionContext) _{{$object.GQLType}}(ctx context.Context, sel ast.SelectionSet{{if not $object.Root}}, obj *{{$object.FullName}} {{end}}) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, {{$object.GQLType|lcFirst}}Implementors, ec.Variables) {{if $object.Root}} ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{ diff --git a/codegen/templates/templates.go b/codegen/templates/templates.go index 3d29b403aac..54eddf522e0 100644 --- a/codegen/templates/templates.go +++ b/codegen/templates/templates.go @@ -96,6 +96,8 @@ 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: diff --git a/codegen/testdata/cfg/gqlgen.yml b/codegen/tests/cfg/gqlgen.yml similarity index 100% rename from codegen/testdata/cfg/gqlgen.yml rename to codegen/tests/cfg/gqlgen.yml diff --git a/codegen/testdata/cfg/malformedconfig.yml b/codegen/tests/cfg/malformedconfig.yml similarity index 100% rename from codegen/testdata/cfg/malformedconfig.yml rename to codegen/tests/cfg/malformedconfig.yml diff --git a/codegen/testdata/cfg/otherdir/.gitkeep b/codegen/tests/cfg/otherdir/.gitkeep similarity index 100% rename from codegen/testdata/cfg/otherdir/.gitkeep rename to codegen/tests/cfg/otherdir/.gitkeep diff --git a/codegen/testdata/cfg/subdir/gqlgen.yaml b/codegen/tests/cfg/subdir/gqlgen.yaml similarity index 100% rename from codegen/testdata/cfg/subdir/gqlgen.yaml rename to codegen/tests/cfg/subdir/gqlgen.yaml diff --git a/codegen/testdata/cfg/unknownkeys.yml b/codegen/tests/cfg/unknownkeys.yml similarity index 100% rename from codegen/testdata/cfg/unknownkeys.yml rename to codegen/tests/cfg/unknownkeys.yml diff --git a/codegen/testdata/element.go b/codegen/tests/element.go similarity index 97% rename from codegen/testdata/element.go rename to codegen/tests/element.go index feaed69f41f..5ba273dcf99 100644 --- a/codegen/testdata/element.go +++ b/codegen/tests/element.go @@ -1,4 +1,4 @@ -package testdata +package tests import ( "context" diff --git a/codegen/testdata/interfaces.go b/codegen/tests/interfaces.go similarity index 95% rename from codegen/testdata/interfaces.go rename to codegen/tests/interfaces.go index ead09b16084..c8daa473045 100644 --- a/codegen/testdata/interfaces.go +++ b/codegen/tests/interfaces.go @@ -1,4 +1,4 @@ -package testdata +package tests import "math" diff --git a/codegen/testdata/introspection/it.go b/codegen/tests/introspection/it.go similarity index 100% rename from codegen/testdata/introspection/it.go rename to codegen/tests/introspection/it.go diff --git a/codegen/testdata/invalid-packagename/invalid-identifier.go b/codegen/tests/invalid-packagename/invalid-identifier.go similarity index 100% rename from codegen/testdata/invalid-packagename/invalid-identifier.go rename to codegen/tests/invalid-packagename/invalid-identifier.go diff --git a/codegen/testdata/recursive.go b/codegen/tests/recursive.go similarity index 79% rename from codegen/testdata/recursive.go rename to codegen/tests/recursive.go index 65854f7721b..c3fccea6ba5 100644 --- a/codegen/testdata/recursive.go +++ b/codegen/tests/recursive.go @@ -1,4 +1,4 @@ -package testdata +package tests type RecursiveInputSlice struct { Self []RecursiveInputSlice diff --git a/codegen/type_build.go b/codegen/type_build.go index ba2874b0572..ab70fd317f1 100644 --- a/codegen/type_build.go +++ b/codegen/type_build.go @@ -1,12 +1,10 @@ package codegen import ( - "fmt" "go/types" "strings" - "github.com/vektah/gqlgen/neelance/common" - "github.com/vektah/gqlgen/neelance/schema" + "github.com/vektah/gqlparser/ast" "golang.org/x/tools/go/loader" ) @@ -50,16 +48,16 @@ func (cfg *Config) bindTypes(imports *Imports, namedTypes NamedTypes, destDir st // namedTypeFromSchema objects for every graphql type, including primitives. // don't recurse into object fields or interfaces yet, lets make sure we have collected everything first. -func namedTypeFromSchema(schemaType schema.NamedType) *NamedType { - switch val := schemaType.(type) { - case *schema.Scalar, *schema.Enum: - return &NamedType{GQLType: val.TypeName(), IsScalar: true} - case *schema.Interface, *schema.Union: - return &NamedType{GQLType: val.TypeName(), IsInterface: true} - case *schema.InputObject: - return &NamedType{GQLType: val.TypeName(), IsInput: true} +func namedTypeFromSchema(schemaType *ast.Definition) *NamedType { + switch schemaType.Kind { + case ast.Scalar, ast.Enum: + return &NamedType{GQLType: schemaType.Name, IsScalar: true} + case ast.Interface, ast.Union: + return &NamedType{GQLType: schemaType.Name, IsInterface: true} + case ast.InputObject: + return &NamedType{GQLType: schemaType.Name, IsInput: true} default: - return &NamedType{GQLType: val.TypeName()} + return &NamedType{GQLType: schemaType.Name} } } @@ -73,40 +71,26 @@ func pkgAndType(name string) (string, string) { return normalizeVendor(strings.Join(parts[:len(parts)-1], ".")), parts[len(parts)-1] } -func (n NamedTypes) getType(t common.Type) *Type { +func (n NamedTypes) getType(t *ast.Type) *Type { var modifiers []string - usePtr := true for { - if _, nonNull := t.(*common.NonNull); nonNull { - usePtr = false - } else if _, nonNull := t.(*common.List); nonNull { - usePtr = true + if t.Elem != nil { + modifiers = append(modifiers, modList) + t = t.Elem } else { - if usePtr { + if !t.NonNull { modifiers = append(modifiers, modPtr) } - usePtr = true - } - - switch val := t.(type) { - case *common.NonNull: - t = val.OfType - case *common.List: - modifiers = append(modifiers, modList) - t = val.OfType - case schema.NamedType: - t := &Type{ - NamedType: n[val.TypeName()], + res := &Type{ + NamedType: n[t.NamedType], Modifiers: modifiers, } - if t.IsInterface { - t.StripPtr() + if res.IsInterface { + res.StripPtr() } - return t - default: - panic(fmt.Errorf("unknown type %T", t)) + return res } } } diff --git a/example/chat/generated.go b/example/chat/generated.go index 3b903cece08..b71ec4f3e37 100644 --- a/example/chat/generated.go +++ b/example/chat/generated.go @@ -8,9 +8,9 @@ import ( strconv "strconv" graphql "github.com/vektah/gqlgen/graphql" - introspection "github.com/vektah/gqlgen/neelance/introspection" - query "github.com/vektah/gqlgen/neelance/query" - schema "github.com/vektah/gqlgen/neelance/schema" + introspection "github.com/vektah/gqlgen/graphql/introspection" + gqlparser "github.com/vektah/gqlparser" + ast "github.com/vektah/gqlparser/ast" ) // MakeExecutableSchema creates an ExecutableSchema from the Resolvers interface. @@ -65,15 +65,15 @@ type executableSchema struct { resolvers Resolvers } -func (e *executableSchema) Schema() *schema.Schema { +func (e *executableSchema) Schema() *ast.Schema { return parsedSchema } -func (e *executableSchema) Query(ctx context.Context, op *query.Operation) *graphql.Response { +func (e *executableSchema) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers} buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte { - data := ec._Query(ctx, op.Selections) + data := ec._Query(ctx, op.SelectionSet) var buf bytes.Buffer data.MarshalGQL(&buf) return buf.Bytes() @@ -85,11 +85,11 @@ func (e *executableSchema) Query(ctx context.Context, op *query.Operation) *grap } } -func (e *executableSchema) Mutation(ctx context.Context, op *query.Operation) *graphql.Response { +func (e *executableSchema) Mutation(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers} buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte { - data := ec._Mutation(ctx, op.Selections) + data := ec._Mutation(ctx, op.SelectionSet) var buf bytes.Buffer data.MarshalGQL(&buf) return buf.Bytes() @@ -101,10 +101,10 @@ func (e *executableSchema) Mutation(ctx context.Context, op *query.Operation) *g } } -func (e *executableSchema) Subscription(ctx context.Context, op *query.Operation) func() *graphql.Response { +func (e *executableSchema) Subscription(ctx context.Context, op *ast.OperationDefinition) func() *graphql.Response { ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers} - next := ec._Subscription(ctx, op.Selections) + next := ec._Subscription(ctx, op.SelectionSet) if ec.Errors != nil { return graphql.OneShot(&graphql.Response{Data: []byte("null"), Errors: ec.Errors}) } @@ -138,7 +138,7 @@ type executionContext struct { var chatroomImplementors = []string{"Chatroom"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Chatroom(ctx context.Context, sel []query.Selection, obj *Chatroom) graphql.Marshaler { +func (ec *executionContext) _Chatroom(ctx context.Context, sel ast.SelectionSet, obj *Chatroom) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, chatroomImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -194,7 +194,7 @@ func (ec *executionContext) _Chatroom_messages(ctx context.Context, field graphq var messageImplementors = []string{"Message"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Message(ctx context.Context, sel []query.Selection, obj *Message) graphql.Marshaler { +func (ec *executionContext) _Message(ctx context.Context, sel ast.SelectionSet, obj *Message) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, messageImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -267,7 +267,7 @@ func (ec *executionContext) _Message_createdAt(ctx context.Context, field graphq var mutationImplementors = []string{"Mutation"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Mutation(ctx context.Context, sel []query.Selection) graphql.Marshaler { +func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, mutationImplementors, ec.Variables) ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{ @@ -346,7 +346,7 @@ func (ec *executionContext) _Mutation_post(ctx context.Context, field graphql.Co var queryImplementors = []string{"Query"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Query(ctx context.Context, sel []query.Selection) graphql.Marshaler { +func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, queryImplementors, ec.Variables) ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{ @@ -362,10 +362,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel []query.Selection) g out.Values[i] = graphql.MarshalString("Query") case "room": out.Values[i] = ec._Query_room(ctx, field) - case "__schema": - out.Values[i] = ec._Query___schema(ctx, field) case "__type": out.Values[i] = ec._Query___type(ctx, field) + case "__schema": + out.Values[i] = ec._Query___schema(ctx, field) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -418,20 +418,6 @@ func (ec *executionContext) _Query_room(ctx context.Context, field graphql.Colle }) } -func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { - rctx := graphql.GetResolverContext(ctx) - rctx.Object = "Query" - rctx.Args = nil - rctx.Field = field - rctx.PushField(field.Alias) - defer rctx.Pop() - res := ec.introspectSchema() - if res == nil { - return graphql.Null - } - return ec.___Schema(ctx, field.Selections, res) -} - func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { args := map[string]interface{}{} var arg0 string @@ -457,10 +443,24 @@ func (ec *executionContext) _Query___type(ctx context.Context, field graphql.Col return ec.___Type(ctx, field.Selections, res) } +func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { + rctx := graphql.GetResolverContext(ctx) + rctx.Object = "Query" + rctx.Args = nil + rctx.Field = field + rctx.PushField(field.Alias) + defer rctx.Pop() + res := ec.introspectSchema() + if res == nil { + return graphql.Null + } + return ec.___Schema(ctx, field.Selections, res) +} + var subscriptionImplementors = []string{"Subscription"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Subscription(ctx context.Context, sel []query.Selection) func() graphql.Marshaler { +func (ec *executionContext) _Subscription(ctx context.Context, sel ast.SelectionSet) func() graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, subscriptionImplementors, ec.Variables) ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{ Object: "Subscription", @@ -510,7 +510,7 @@ func (ec *executionContext) _Subscription_messageAdded(ctx context.Context, fiel var __DirectiveImplementors = []string{"__Directive"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Directive(ctx context.Context, sel []query.Selection, obj *introspection.Directive) graphql.Marshaler { +func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __DirectiveImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -543,7 +543,7 @@ func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -554,11 +554,8 @@ func (ec *executionContext) ___Directive_description(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___Directive_locations(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) graphql.Marshaler { @@ -568,7 +565,7 @@ func (ec *executionContext) ___Directive_locations(ctx context.Context, field gr rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Locations() + res := obj.Locations arr1 := graphql.Array{} for idx1 := range res { arr1 = append(arr1, func() graphql.Marshaler { @@ -588,7 +585,7 @@ func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Args() + res := obj.Args arr1 := graphql.Array{} for idx1 := range res { arr1 = append(arr1, func() graphql.Marshaler { @@ -604,7 +601,7 @@ func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql var __EnumValueImplementors = []string{"__EnumValue"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___EnumValue(ctx context.Context, sel []query.Selection, obj *introspection.EnumValue) graphql.Marshaler { +func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __EnumValueImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -637,7 +634,7 @@ func (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -648,11 +645,8 @@ func (ec *executionContext) ___EnumValue_description(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) graphql.Marshaler { @@ -662,7 +656,7 @@ func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.IsDeprecated() + res := obj.IsDeprecated return graphql.MarshalBoolean(res) } @@ -673,17 +667,14 @@ func (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.DeprecationReason() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.DeprecationReason + return graphql.MarshalString(res) } var __FieldImplementors = []string{"__Field"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Field(ctx context.Context, sel []query.Selection, obj *introspection.Field) graphql.Marshaler { +func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __FieldImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -720,7 +711,7 @@ func (ec *executionContext) ___Field_name(ctx context.Context, field graphql.Col rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -731,11 +722,8 @@ func (ec *executionContext) ___Field_description(ctx context.Context, field grap rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) graphql.Marshaler { @@ -745,7 +733,7 @@ func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.Col rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Args() + res := obj.Args arr1 := graphql.Array{} for idx1 := range res { arr1 = append(arr1, func() graphql.Marshaler { @@ -765,8 +753,11 @@ func (ec *executionContext) ___Field_type(ctx context.Context, field graphql.Col rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Type() - return ec.___Type(ctx, field.Selections, &res) + res := obj.Type + if res == nil { + return graphql.Null + } + return ec.___Type(ctx, field.Selections, res) } func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) graphql.Marshaler { @@ -776,7 +767,7 @@ func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field gra rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.IsDeprecated() + res := obj.IsDeprecated return graphql.MarshalBoolean(res) } @@ -787,17 +778,14 @@ func (ec *executionContext) ___Field_deprecationReason(ctx context.Context, fiel rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.DeprecationReason() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.DeprecationReason + return graphql.MarshalString(res) } var __InputValueImplementors = []string{"__InputValue"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___InputValue(ctx context.Context, sel []query.Selection, obj *introspection.InputValue) graphql.Marshaler { +func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __InputValueImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -830,7 +818,7 @@ func (ec *executionContext) ___InputValue_name(ctx context.Context, field graphq rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -841,11 +829,8 @@ func (ec *executionContext) ___InputValue_description(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) graphql.Marshaler { @@ -855,8 +840,11 @@ func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphq rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Type() - return ec.___Type(ctx, field.Selections, &res) + res := obj.Type + if res == nil { + return graphql.Null + } + return ec.___Type(ctx, field.Selections, res) } func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) graphql.Marshaler { @@ -866,17 +854,14 @@ func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, fiel rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.DefaultValue() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.DefaultValue + return graphql.MarshalString(res) } var __SchemaImplementors = []string{"__Schema"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Schema(ctx context.Context, sel []query.Selection, obj *introspection.Schema) graphql.Marshaler { +func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __SchemaImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -932,7 +917,10 @@ func (ec *executionContext) ___Schema_queryType(ctx context.Context, field graph rctx.PushField(field.Alias) defer rctx.Pop() res := obj.QueryType() - return ec.___Type(ctx, field.Selections, &res) + if res == nil { + return graphql.Null + } + return ec.___Type(ctx, field.Selections, res) } func (ec *executionContext) ___Schema_mutationType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) graphql.Marshaler { @@ -986,7 +974,7 @@ func (ec *executionContext) ___Schema_directives(ctx context.Context, field grap var __TypeImplementors = []string{"__Type"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Type(ctx context.Context, sel []query.Selection, obj *introspection.Type) graphql.Marshaler { +func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __TypeImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -1041,10 +1029,7 @@ func (ec *executionContext) ___Type_name(ctx context.Context, field graphql.Coll rctx.PushField(field.Alias) defer rctx.Pop() res := obj.Name() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + return graphql.MarshalString(res) } func (ec *executionContext) ___Type_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) graphql.Marshaler { @@ -1055,10 +1040,7 @@ func (ec *executionContext) ___Type_description(ctx context.Context, field graph rctx.PushField(field.Alias) defer rctx.Pop() res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + return graphql.MarshalString(res) } func (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) graphql.Marshaler { @@ -1202,14 +1184,10 @@ func (ec *executionContext) introspectSchema() *introspection.Schema { } func (ec *executionContext) introspectType(name string) *introspection.Type { - t := parsedSchema.Resolve(name) - if t == nil { - return nil - } - return introspection.WrapType(t) + return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]) } -var parsedSchema = schema.MustParse(`type Chatroom { +var parsedSchema = gqlparser.MustLoadSchema(introspection.Prelude + `type Chatroom { name: String! messages: [Message!]! } diff --git a/example/dataloader/dataloader_test.go b/example/dataloader/dataloader_test.go index 38d05d88b7e..c10bb574724 100644 --- a/example/dataloader/dataloader_test.go +++ b/example/dataloader/dataloader_test.go @@ -6,8 +6,8 @@ import ( "github.com/stretchr/testify/require" "github.com/vektah/gqlgen/client" + "github.com/vektah/gqlgen/graphql/introspection" "github.com/vektah/gqlgen/handler" - "github.com/vektah/gqlgen/neelance/introspection" ) func TestTodo(t *testing.T) { diff --git a/example/dataloader/generated.go b/example/dataloader/generated.go index 0893a01544d..c5351169c35 100644 --- a/example/dataloader/generated.go +++ b/example/dataloader/generated.go @@ -8,9 +8,9 @@ import ( strconv "strconv" graphql "github.com/vektah/gqlgen/graphql" - introspection "github.com/vektah/gqlgen/neelance/introspection" - query "github.com/vektah/gqlgen/neelance/query" - schema "github.com/vektah/gqlgen/neelance/schema" + introspection "github.com/vektah/gqlgen/graphql/introspection" + gqlparser "github.com/vektah/gqlparser" + ast "github.com/vektah/gqlparser/ast" ) // MakeExecutableSchema creates an ExecutableSchema from the Resolvers interface. @@ -77,15 +77,15 @@ type executableSchema struct { resolvers Resolvers } -func (e *executableSchema) Schema() *schema.Schema { +func (e *executableSchema) Schema() *ast.Schema { return parsedSchema } -func (e *executableSchema) Query(ctx context.Context, op *query.Operation) *graphql.Response { +func (e *executableSchema) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers} buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte { - data := ec._Query(ctx, op.Selections) + data := ec._Query(ctx, op.SelectionSet) var buf bytes.Buffer data.MarshalGQL(&buf) return buf.Bytes() @@ -97,11 +97,11 @@ func (e *executableSchema) Query(ctx context.Context, op *query.Operation) *grap } } -func (e *executableSchema) Mutation(ctx context.Context, op *query.Operation) *graphql.Response { +func (e *executableSchema) Mutation(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { return graphql.ErrorResponse(ctx, "mutations are not supported") } -func (e *executableSchema) Subscription(ctx context.Context, op *query.Operation) func() *graphql.Response { +func (e *executableSchema) Subscription(ctx context.Context, op *ast.OperationDefinition) func() *graphql.Response { return graphql.OneShot(graphql.ErrorResponse(ctx, "subscriptions are not supported")) } @@ -114,7 +114,7 @@ type executionContext struct { var addressImplementors = []string{"Address"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Address(ctx context.Context, sel []query.Selection, obj *Address) graphql.Marshaler { +func (ec *executionContext) _Address(ctx context.Context, sel ast.SelectionSet, obj *Address) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, addressImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -174,7 +174,7 @@ func (ec *executionContext) _Address_country(ctx context.Context, field graphql. var customerImplementors = []string{"Customer"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Customer(ctx context.Context, sel []query.Selection, obj *Customer) graphql.Marshaler { +func (ec *executionContext) _Customer(ctx context.Context, sel ast.SelectionSet, obj *Customer) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, customerImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -297,7 +297,7 @@ func (ec *executionContext) _Customer_orders(ctx context.Context, field graphql. var itemImplementors = []string{"Item"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Item(ctx context.Context, sel []query.Selection, obj *Item) graphql.Marshaler { +func (ec *executionContext) _Item(ctx context.Context, sel ast.SelectionSet, obj *Item) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, itemImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -331,7 +331,7 @@ func (ec *executionContext) _Item_name(ctx context.Context, field graphql.Collec var orderImplementors = []string{"Order"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Order(ctx context.Context, sel []query.Selection, obj *Order) graphql.Marshaler { +func (ec *executionContext) _Order(ctx context.Context, sel ast.SelectionSet, obj *Order) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, orderImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -432,7 +432,7 @@ func (ec *executionContext) _Order_items(ctx context.Context, field graphql.Coll var queryImplementors = []string{"Query"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Query(ctx context.Context, sel []query.Selection) graphql.Marshaler { +func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, queryImplementors, ec.Variables) ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{ @@ -450,10 +450,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel []query.Selection) g out.Values[i] = ec._Query_customers(ctx, field) case "torture": out.Values[i] = ec._Query_torture(ctx, field) - case "__schema": - out.Values[i] = ec._Query___schema(ctx, field) case "__type": out.Values[i] = ec._Query___type(ctx, field) + case "__schema": + out.Values[i] = ec._Query___schema(ctx, field) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -578,20 +578,6 @@ func (ec *executionContext) _Query_torture(ctx context.Context, field graphql.Co }) } -func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { - rctx := graphql.GetResolverContext(ctx) - rctx.Object = "Query" - rctx.Args = nil - rctx.Field = field - rctx.PushField(field.Alias) - defer rctx.Pop() - res := ec.introspectSchema() - if res == nil { - return graphql.Null - } - return ec.___Schema(ctx, field.Selections, res) -} - func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { args := map[string]interface{}{} var arg0 string @@ -617,10 +603,24 @@ func (ec *executionContext) _Query___type(ctx context.Context, field graphql.Col return ec.___Type(ctx, field.Selections, res) } +func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { + rctx := graphql.GetResolverContext(ctx) + rctx.Object = "Query" + rctx.Args = nil + rctx.Field = field + rctx.PushField(field.Alias) + defer rctx.Pop() + res := ec.introspectSchema() + if res == nil { + return graphql.Null + } + return ec.___Schema(ctx, field.Selections, res) +} + var __DirectiveImplementors = []string{"__Directive"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Directive(ctx context.Context, sel []query.Selection, obj *introspection.Directive) graphql.Marshaler { +func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __DirectiveImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -653,7 +653,7 @@ func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -664,11 +664,8 @@ func (ec *executionContext) ___Directive_description(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___Directive_locations(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) graphql.Marshaler { @@ -678,7 +675,7 @@ func (ec *executionContext) ___Directive_locations(ctx context.Context, field gr rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Locations() + res := obj.Locations arr1 := graphql.Array{} for idx1 := range res { arr1 = append(arr1, func() graphql.Marshaler { @@ -698,7 +695,7 @@ func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Args() + res := obj.Args arr1 := graphql.Array{} for idx1 := range res { arr1 = append(arr1, func() graphql.Marshaler { @@ -714,7 +711,7 @@ func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql var __EnumValueImplementors = []string{"__EnumValue"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___EnumValue(ctx context.Context, sel []query.Selection, obj *introspection.EnumValue) graphql.Marshaler { +func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __EnumValueImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -747,7 +744,7 @@ func (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -758,11 +755,8 @@ func (ec *executionContext) ___EnumValue_description(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) graphql.Marshaler { @@ -772,7 +766,7 @@ func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.IsDeprecated() + res := obj.IsDeprecated return graphql.MarshalBoolean(res) } @@ -783,17 +777,14 @@ func (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.DeprecationReason() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.DeprecationReason + return graphql.MarshalString(res) } var __FieldImplementors = []string{"__Field"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Field(ctx context.Context, sel []query.Selection, obj *introspection.Field) graphql.Marshaler { +func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __FieldImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -830,7 +821,7 @@ func (ec *executionContext) ___Field_name(ctx context.Context, field graphql.Col rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -841,11 +832,8 @@ func (ec *executionContext) ___Field_description(ctx context.Context, field grap rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) graphql.Marshaler { @@ -855,7 +843,7 @@ func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.Col rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Args() + res := obj.Args arr1 := graphql.Array{} for idx1 := range res { arr1 = append(arr1, func() graphql.Marshaler { @@ -875,8 +863,11 @@ func (ec *executionContext) ___Field_type(ctx context.Context, field graphql.Col rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Type() - return ec.___Type(ctx, field.Selections, &res) + res := obj.Type + if res == nil { + return graphql.Null + } + return ec.___Type(ctx, field.Selections, res) } func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) graphql.Marshaler { @@ -886,7 +877,7 @@ func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field gra rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.IsDeprecated() + res := obj.IsDeprecated return graphql.MarshalBoolean(res) } @@ -897,17 +888,14 @@ func (ec *executionContext) ___Field_deprecationReason(ctx context.Context, fiel rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.DeprecationReason() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.DeprecationReason + return graphql.MarshalString(res) } var __InputValueImplementors = []string{"__InputValue"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___InputValue(ctx context.Context, sel []query.Selection, obj *introspection.InputValue) graphql.Marshaler { +func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __InputValueImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -940,7 +928,7 @@ func (ec *executionContext) ___InputValue_name(ctx context.Context, field graphq rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -951,11 +939,8 @@ func (ec *executionContext) ___InputValue_description(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) graphql.Marshaler { @@ -965,8 +950,11 @@ func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphq rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Type() - return ec.___Type(ctx, field.Selections, &res) + res := obj.Type + if res == nil { + return graphql.Null + } + return ec.___Type(ctx, field.Selections, res) } func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) graphql.Marshaler { @@ -976,17 +964,14 @@ func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, fiel rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.DefaultValue() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.DefaultValue + return graphql.MarshalString(res) } var __SchemaImplementors = []string{"__Schema"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Schema(ctx context.Context, sel []query.Selection, obj *introspection.Schema) graphql.Marshaler { +func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __SchemaImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -1042,7 +1027,10 @@ func (ec *executionContext) ___Schema_queryType(ctx context.Context, field graph rctx.PushField(field.Alias) defer rctx.Pop() res := obj.QueryType() - return ec.___Type(ctx, field.Selections, &res) + if res == nil { + return graphql.Null + } + return ec.___Type(ctx, field.Selections, res) } func (ec *executionContext) ___Schema_mutationType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) graphql.Marshaler { @@ -1096,7 +1084,7 @@ func (ec *executionContext) ___Schema_directives(ctx context.Context, field grap var __TypeImplementors = []string{"__Type"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Type(ctx context.Context, sel []query.Selection, obj *introspection.Type) graphql.Marshaler { +func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __TypeImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -1151,10 +1139,7 @@ func (ec *executionContext) ___Type_name(ctx context.Context, field graphql.Coll rctx.PushField(field.Alias) defer rctx.Pop() res := obj.Name() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + return graphql.MarshalString(res) } func (ec *executionContext) ___Type_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) graphql.Marshaler { @@ -1165,10 +1150,7 @@ func (ec *executionContext) ___Type_description(ctx context.Context, field graph rctx.PushField(field.Alias) defer rctx.Pop() res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + return graphql.MarshalString(res) } func (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) graphql.Marshaler { @@ -1312,14 +1294,10 @@ func (ec *executionContext) introspectSchema() *introspection.Schema { } func (ec *executionContext) introspectType(name string) *introspection.Type { - t := parsedSchema.Resolve(name) - if t == nil { - return nil - } - return introspection.WrapType(t) + return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]) } -var parsedSchema = schema.MustParse(`type Query { +var parsedSchema = gqlparser.MustLoadSchema(introspection.Prelude + `type Query { customers: [Customer!] # this method is here to test code generation of nested arrays diff --git a/example/scalars/generated.go b/example/scalars/generated.go index 8d099b7c7eb..e2cf987595a 100644 --- a/example/scalars/generated.go +++ b/example/scalars/generated.go @@ -11,9 +11,9 @@ import ( model "github.com/vektah/gqlgen/example/scalars/model" graphql "github.com/vektah/gqlgen/graphql" - introspection "github.com/vektah/gqlgen/neelance/introspection" - query "github.com/vektah/gqlgen/neelance/query" - schema "github.com/vektah/gqlgen/neelance/schema" + introspection "github.com/vektah/gqlgen/graphql/introspection" + gqlparser "github.com/vektah/gqlparser" + ast "github.com/vektah/gqlparser/ast" ) // MakeExecutableSchema creates an ExecutableSchema from the Resolvers interface. @@ -71,15 +71,15 @@ type executableSchema struct { resolvers Resolvers } -func (e *executableSchema) Schema() *schema.Schema { +func (e *executableSchema) Schema() *ast.Schema { return parsedSchema } -func (e *executableSchema) Query(ctx context.Context, op *query.Operation) *graphql.Response { +func (e *executableSchema) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers} buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte { - data := ec._Query(ctx, op.Selections) + data := ec._Query(ctx, op.SelectionSet) var buf bytes.Buffer data.MarshalGQL(&buf) return buf.Bytes() @@ -91,11 +91,11 @@ func (e *executableSchema) Query(ctx context.Context, op *query.Operation) *grap } } -func (e *executableSchema) Mutation(ctx context.Context, op *query.Operation) *graphql.Response { +func (e *executableSchema) Mutation(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { return graphql.ErrorResponse(ctx, "mutations are not supported") } -func (e *executableSchema) Subscription(ctx context.Context, op *query.Operation) func() *graphql.Response { +func (e *executableSchema) Subscription(ctx context.Context, op *ast.OperationDefinition) func() *graphql.Response { return graphql.OneShot(graphql.ErrorResponse(ctx, "subscriptions are not supported")) } @@ -108,7 +108,7 @@ type executionContext struct { var addressImplementors = []string{"Address"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Address(ctx context.Context, sel []query.Selection, obj *model.Address) graphql.Marshaler { +func (ec *executionContext) _Address(ctx context.Context, sel ast.SelectionSet, obj *model.Address) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, addressImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -158,7 +158,7 @@ func (ec *executionContext) _Address_location(ctx context.Context, field graphql var queryImplementors = []string{"Query"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Query(ctx context.Context, sel []query.Selection) graphql.Marshaler { +func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, queryImplementors, ec.Variables) ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{ @@ -176,10 +176,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel []query.Selection) g out.Values[i] = ec._Query_user(ctx, field) case "search": out.Values[i] = ec._Query_search(ctx, field) - case "__schema": - out.Values[i] = ec._Query___schema(ctx, field) case "__type": out.Values[i] = ec._Query___type(ctx, field) + case "__schema": + out.Values[i] = ec._Query___schema(ctx, field) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -291,20 +291,6 @@ func (ec *executionContext) _Query_search(ctx context.Context, field graphql.Col }) } -func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { - rctx := graphql.GetResolverContext(ctx) - rctx.Object = "Query" - rctx.Args = nil - rctx.Field = field - rctx.PushField(field.Alias) - defer rctx.Pop() - res := ec.introspectSchema() - if res == nil { - return graphql.Null - } - return ec.___Schema(ctx, field.Selections, res) -} - func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { args := map[string]interface{}{} var arg0 string @@ -330,10 +316,24 @@ func (ec *executionContext) _Query___type(ctx context.Context, field graphql.Col return ec.___Type(ctx, field.Selections, res) } +func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { + rctx := graphql.GetResolverContext(ctx) + rctx.Object = "Query" + rctx.Args = nil + rctx.Field = field + rctx.PushField(field.Alias) + defer rctx.Pop() + res := ec.introspectSchema() + if res == nil { + return graphql.Null + } + return ec.___Schema(ctx, field.Selections, res) +} + var userImplementors = []string{"User"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _User(ctx context.Context, sel []query.Selection, obj *model.User) graphql.Marshaler { +func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj *model.User) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, userImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -496,7 +496,7 @@ func (ec *executionContext) _User_tier(ctx context.Context, field graphql.Collec var __DirectiveImplementors = []string{"__Directive"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Directive(ctx context.Context, sel []query.Selection, obj *introspection.Directive) graphql.Marshaler { +func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __DirectiveImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -529,7 +529,7 @@ func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -540,11 +540,8 @@ func (ec *executionContext) ___Directive_description(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___Directive_locations(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) graphql.Marshaler { @@ -554,7 +551,7 @@ func (ec *executionContext) ___Directive_locations(ctx context.Context, field gr rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Locations() + res := obj.Locations arr1 := graphql.Array{} for idx1 := range res { arr1 = append(arr1, func() graphql.Marshaler { @@ -574,7 +571,7 @@ func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Args() + res := obj.Args arr1 := graphql.Array{} for idx1 := range res { arr1 = append(arr1, func() graphql.Marshaler { @@ -590,7 +587,7 @@ func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql var __EnumValueImplementors = []string{"__EnumValue"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___EnumValue(ctx context.Context, sel []query.Selection, obj *introspection.EnumValue) graphql.Marshaler { +func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __EnumValueImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -623,7 +620,7 @@ func (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -634,11 +631,8 @@ func (ec *executionContext) ___EnumValue_description(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) graphql.Marshaler { @@ -648,7 +642,7 @@ func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.IsDeprecated() + res := obj.IsDeprecated return graphql.MarshalBoolean(res) } @@ -659,17 +653,14 @@ func (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.DeprecationReason() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.DeprecationReason + return graphql.MarshalString(res) } var __FieldImplementors = []string{"__Field"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Field(ctx context.Context, sel []query.Selection, obj *introspection.Field) graphql.Marshaler { +func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __FieldImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -706,7 +697,7 @@ func (ec *executionContext) ___Field_name(ctx context.Context, field graphql.Col rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -717,11 +708,8 @@ func (ec *executionContext) ___Field_description(ctx context.Context, field grap rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) graphql.Marshaler { @@ -731,7 +719,7 @@ func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.Col rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Args() + res := obj.Args arr1 := graphql.Array{} for idx1 := range res { arr1 = append(arr1, func() graphql.Marshaler { @@ -751,8 +739,11 @@ func (ec *executionContext) ___Field_type(ctx context.Context, field graphql.Col rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Type() - return ec.___Type(ctx, field.Selections, &res) + res := obj.Type + if res == nil { + return graphql.Null + } + return ec.___Type(ctx, field.Selections, res) } func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) graphql.Marshaler { @@ -762,7 +753,7 @@ func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field gra rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.IsDeprecated() + res := obj.IsDeprecated return graphql.MarshalBoolean(res) } @@ -773,17 +764,14 @@ func (ec *executionContext) ___Field_deprecationReason(ctx context.Context, fiel rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.DeprecationReason() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.DeprecationReason + return graphql.MarshalString(res) } var __InputValueImplementors = []string{"__InputValue"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___InputValue(ctx context.Context, sel []query.Selection, obj *introspection.InputValue) graphql.Marshaler { +func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __InputValueImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -816,7 +804,7 @@ func (ec *executionContext) ___InputValue_name(ctx context.Context, field graphq rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -827,11 +815,8 @@ func (ec *executionContext) ___InputValue_description(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) graphql.Marshaler { @@ -841,8 +826,11 @@ func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphq rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Type() - return ec.___Type(ctx, field.Selections, &res) + res := obj.Type + if res == nil { + return graphql.Null + } + return ec.___Type(ctx, field.Selections, res) } func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) graphql.Marshaler { @@ -852,17 +840,14 @@ func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, fiel rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.DefaultValue() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.DefaultValue + return graphql.MarshalString(res) } var __SchemaImplementors = []string{"__Schema"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Schema(ctx context.Context, sel []query.Selection, obj *introspection.Schema) graphql.Marshaler { +func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __SchemaImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -918,7 +903,10 @@ func (ec *executionContext) ___Schema_queryType(ctx context.Context, field graph rctx.PushField(field.Alias) defer rctx.Pop() res := obj.QueryType() - return ec.___Type(ctx, field.Selections, &res) + if res == nil { + return graphql.Null + } + return ec.___Type(ctx, field.Selections, res) } func (ec *executionContext) ___Schema_mutationType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) graphql.Marshaler { @@ -972,7 +960,7 @@ func (ec *executionContext) ___Schema_directives(ctx context.Context, field grap var __TypeImplementors = []string{"__Type"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Type(ctx context.Context, sel []query.Selection, obj *introspection.Type) graphql.Marshaler { +func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __TypeImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -1027,10 +1015,7 @@ func (ec *executionContext) ___Type_name(ctx context.Context, field graphql.Coll rctx.PushField(field.Alias) defer rctx.Pop() res := obj.Name() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + return graphql.MarshalString(res) } func (ec *executionContext) ___Type_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) graphql.Marshaler { @@ -1041,10 +1026,7 @@ func (ec *executionContext) ___Type_description(ctx context.Context, field graph rctx.PushField(field.Alias) defer rctx.Pop() res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + return graphql.MarshalString(res) } func (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) graphql.Marshaler { @@ -1231,14 +1213,10 @@ func (ec *executionContext) introspectSchema() *introspection.Schema { } func (ec *executionContext) introspectType(name string) *introspection.Type { - t := parsedSchema.Resolve(name) - if t == nil { - return nil - } - return introspection.WrapType(t) + return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]) } -var parsedSchema = schema.MustParse(`type Query { +var parsedSchema = gqlparser.MustLoadSchema(introspection.Prelude + `type Query { user(id: ID!): User search(input: SearchArgs = {location: "37,144", isBanned: false}): [User!]! } diff --git a/example/scalars/model/model.go b/example/scalars/model/model.go index 7771affd63b..a3940e95003 100644 --- a/example/scalars/model/model.go +++ b/example/scalars/model/model.go @@ -68,8 +68,8 @@ func MarshalTimestamp(t time.Time) graphql.Marshaler { // Unmarshal{Typename} is only required if the scalar appears as an input. The raw values have already been decoded // from json into int/float64/bool/nil/map[string]interface/[]interface func UnmarshalTimestamp(v interface{}) (time.Time, error) { - if tmpStr, ok := v.(int); ok { - return time.Unix(int64(tmpStr), 0), nil + if tmpStr, ok := v.(int64); ok { + return time.Unix(tmpStr, 0), nil } return time.Time{}, errors.New("time should be a unix timestamp") } diff --git a/example/scalars/scalar_test.go b/example/scalars/scalar_test.go index 226c0ed1b3d..96a3eee409c 100644 --- a/example/scalars/scalar_test.go +++ b/example/scalars/scalar_test.go @@ -7,8 +7,8 @@ import ( "github.com/stretchr/testify/require" "github.com/vektah/gqlgen/client" + "github.com/vektah/gqlgen/graphql/introspection" "github.com/vektah/gqlgen/handler" - introspection "github.com/vektah/gqlgen/neelance/introspection" ) type RawUser struct { diff --git a/example/selection/generated.go b/example/selection/generated.go index 71d5e8de99c..55dcf9b6325 100644 --- a/example/selection/generated.go +++ b/example/selection/generated.go @@ -9,9 +9,9 @@ import ( strconv "strconv" graphql "github.com/vektah/gqlgen/graphql" - introspection "github.com/vektah/gqlgen/neelance/introspection" - query "github.com/vektah/gqlgen/neelance/query" - schema "github.com/vektah/gqlgen/neelance/schema" + introspection "github.com/vektah/gqlgen/graphql/introspection" + gqlparser "github.com/vektah/gqlparser" + ast "github.com/vektah/gqlparser/ast" ) // MakeExecutableSchema creates an ExecutableSchema from the Resolvers interface. @@ -47,15 +47,15 @@ type executableSchema struct { resolvers Resolvers } -func (e *executableSchema) Schema() *schema.Schema { +func (e *executableSchema) Schema() *ast.Schema { return parsedSchema } -func (e *executableSchema) Query(ctx context.Context, op *query.Operation) *graphql.Response { +func (e *executableSchema) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers} buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte { - data := ec._Query(ctx, op.Selections) + data := ec._Query(ctx, op.SelectionSet) var buf bytes.Buffer data.MarshalGQL(&buf) return buf.Bytes() @@ -67,11 +67,11 @@ func (e *executableSchema) Query(ctx context.Context, op *query.Operation) *grap } } -func (e *executableSchema) Mutation(ctx context.Context, op *query.Operation) *graphql.Response { +func (e *executableSchema) Mutation(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { return graphql.ErrorResponse(ctx, "mutations are not supported") } -func (e *executableSchema) Subscription(ctx context.Context, op *query.Operation) func() *graphql.Response { +func (e *executableSchema) Subscription(ctx context.Context, op *ast.OperationDefinition) func() *graphql.Response { return graphql.OneShot(graphql.ErrorResponse(ctx, "subscriptions are not supported")) } @@ -84,7 +84,7 @@ type executionContext struct { var likeImplementors = []string{"Like", "Event"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Like(ctx context.Context, sel []query.Selection, obj *Like) graphql.Marshaler { +func (ec *executionContext) _Like(ctx context.Context, sel ast.SelectionSet, obj *Like) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, likeImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -175,7 +175,7 @@ func (ec *executionContext) _Like_collected(ctx context.Context, field graphql.C var postImplementors = []string{"Post", "Event"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Post(ctx context.Context, sel []query.Selection, obj *Post) graphql.Marshaler { +func (ec *executionContext) _Post(ctx context.Context, sel ast.SelectionSet, obj *Post) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, postImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -266,7 +266,7 @@ func (ec *executionContext) _Post_collected(ctx context.Context, field graphql.C var queryImplementors = []string{"Query"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Query(ctx context.Context, sel []query.Selection) graphql.Marshaler { +func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, queryImplementors, ec.Variables) ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{ @@ -282,10 +282,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel []query.Selection) g out.Values[i] = graphql.MarshalString("Query") case "events": out.Values[i] = ec._Query_events(ctx, field) - case "__schema": - out.Values[i] = ec._Query___schema(ctx, field) case "__type": out.Values[i] = ec._Query___type(ctx, field) + case "__schema": + out.Values[i] = ec._Query___schema(ctx, field) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -333,20 +333,6 @@ func (ec *executionContext) _Query_events(ctx context.Context, field graphql.Col }) } -func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { - rctx := graphql.GetResolverContext(ctx) - rctx.Object = "Query" - rctx.Args = nil - rctx.Field = field - rctx.PushField(field.Alias) - defer rctx.Pop() - res := ec.introspectSchema() - if res == nil { - return graphql.Null - } - return ec.___Schema(ctx, field.Selections, res) -} - func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { args := map[string]interface{}{} var arg0 string @@ -372,10 +358,24 @@ func (ec *executionContext) _Query___type(ctx context.Context, field graphql.Col return ec.___Type(ctx, field.Selections, res) } +func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { + rctx := graphql.GetResolverContext(ctx) + rctx.Object = "Query" + rctx.Args = nil + rctx.Field = field + rctx.PushField(field.Alias) + defer rctx.Pop() + res := ec.introspectSchema() + if res == nil { + return graphql.Null + } + return ec.___Schema(ctx, field.Selections, res) +} + var __DirectiveImplementors = []string{"__Directive"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Directive(ctx context.Context, sel []query.Selection, obj *introspection.Directive) graphql.Marshaler { +func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __DirectiveImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -408,7 +408,7 @@ func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -419,11 +419,8 @@ func (ec *executionContext) ___Directive_description(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___Directive_locations(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) graphql.Marshaler { @@ -433,7 +430,7 @@ func (ec *executionContext) ___Directive_locations(ctx context.Context, field gr rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Locations() + res := obj.Locations arr1 := graphql.Array{} for idx1 := range res { arr1 = append(arr1, func() graphql.Marshaler { @@ -453,7 +450,7 @@ func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Args() + res := obj.Args arr1 := graphql.Array{} for idx1 := range res { arr1 = append(arr1, func() graphql.Marshaler { @@ -469,7 +466,7 @@ func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql var __EnumValueImplementors = []string{"__EnumValue"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___EnumValue(ctx context.Context, sel []query.Selection, obj *introspection.EnumValue) graphql.Marshaler { +func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __EnumValueImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -502,7 +499,7 @@ func (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -513,11 +510,8 @@ func (ec *executionContext) ___EnumValue_description(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) graphql.Marshaler { @@ -527,7 +521,7 @@ func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.IsDeprecated() + res := obj.IsDeprecated return graphql.MarshalBoolean(res) } @@ -538,17 +532,14 @@ func (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.DeprecationReason() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.DeprecationReason + return graphql.MarshalString(res) } var __FieldImplementors = []string{"__Field"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Field(ctx context.Context, sel []query.Selection, obj *introspection.Field) graphql.Marshaler { +func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __FieldImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -585,7 +576,7 @@ func (ec *executionContext) ___Field_name(ctx context.Context, field graphql.Col rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -596,11 +587,8 @@ func (ec *executionContext) ___Field_description(ctx context.Context, field grap rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) graphql.Marshaler { @@ -610,7 +598,7 @@ func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.Col rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Args() + res := obj.Args arr1 := graphql.Array{} for idx1 := range res { arr1 = append(arr1, func() graphql.Marshaler { @@ -630,8 +618,11 @@ func (ec *executionContext) ___Field_type(ctx context.Context, field graphql.Col rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Type() - return ec.___Type(ctx, field.Selections, &res) + res := obj.Type + if res == nil { + return graphql.Null + } + return ec.___Type(ctx, field.Selections, res) } func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) graphql.Marshaler { @@ -641,7 +632,7 @@ func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field gra rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.IsDeprecated() + res := obj.IsDeprecated return graphql.MarshalBoolean(res) } @@ -652,17 +643,14 @@ func (ec *executionContext) ___Field_deprecationReason(ctx context.Context, fiel rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.DeprecationReason() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.DeprecationReason + return graphql.MarshalString(res) } var __InputValueImplementors = []string{"__InputValue"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___InputValue(ctx context.Context, sel []query.Selection, obj *introspection.InputValue) graphql.Marshaler { +func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __InputValueImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -695,7 +683,7 @@ func (ec *executionContext) ___InputValue_name(ctx context.Context, field graphq rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -706,11 +694,8 @@ func (ec *executionContext) ___InputValue_description(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) graphql.Marshaler { @@ -720,8 +705,11 @@ func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphq rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Type() - return ec.___Type(ctx, field.Selections, &res) + res := obj.Type + if res == nil { + return graphql.Null + } + return ec.___Type(ctx, field.Selections, res) } func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) graphql.Marshaler { @@ -731,17 +719,14 @@ func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, fiel rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.DefaultValue() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.DefaultValue + return graphql.MarshalString(res) } var __SchemaImplementors = []string{"__Schema"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Schema(ctx context.Context, sel []query.Selection, obj *introspection.Schema) graphql.Marshaler { +func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __SchemaImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -797,7 +782,10 @@ func (ec *executionContext) ___Schema_queryType(ctx context.Context, field graph rctx.PushField(field.Alias) defer rctx.Pop() res := obj.QueryType() - return ec.___Type(ctx, field.Selections, &res) + if res == nil { + return graphql.Null + } + return ec.___Type(ctx, field.Selections, res) } func (ec *executionContext) ___Schema_mutationType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) graphql.Marshaler { @@ -851,7 +839,7 @@ func (ec *executionContext) ___Schema_directives(ctx context.Context, field grap var __TypeImplementors = []string{"__Type"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Type(ctx context.Context, sel []query.Selection, obj *introspection.Type) graphql.Marshaler { +func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __TypeImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -906,10 +894,7 @@ func (ec *executionContext) ___Type_name(ctx context.Context, field graphql.Coll rctx.PushField(field.Alias) defer rctx.Pop() res := obj.Name() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + return graphql.MarshalString(res) } func (ec *executionContext) ___Type_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) graphql.Marshaler { @@ -920,10 +905,7 @@ func (ec *executionContext) ___Type_description(ctx context.Context, field graph rctx.PushField(field.Alias) defer rctx.Pop() res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + return graphql.MarshalString(res) } func (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) graphql.Marshaler { @@ -1062,7 +1044,7 @@ func (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.Co return ec.___Type(ctx, field.Selections, res) } -func (ec *executionContext) _Event(ctx context.Context, sel []query.Selection, obj *Event) graphql.Marshaler { +func (ec *executionContext) _Event(ctx context.Context, sel ast.SelectionSet, obj *Event) graphql.Marshaler { switch obj := (*obj).(type) { case nil: return graphql.Null @@ -1084,14 +1066,10 @@ func (ec *executionContext) introspectSchema() *introspection.Schema { } func (ec *executionContext) introspectType(name string) *introspection.Type { - t := parsedSchema.Resolve(name) - if t == nil { - return nil - } - return introspection.WrapType(t) + return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]) } -var parsedSchema = schema.MustParse(`interface Event { +var parsedSchema = gqlparser.MustLoadSchema(introspection.Prelude + `interface Event { selection: [String!] collected: [String!] } diff --git a/example/selection/selection.go b/example/selection/selection.go index 9ccc8590d0f..7d11be04572 100644 --- a/example/selection/selection.go +++ b/example/selection/selection.go @@ -8,7 +8,7 @@ import ( "time" "github.com/vektah/gqlgen/graphql" - query "github.com/vektah/gqlgen/neelance/query" + "github.com/vektah/gqlparser/ast" ) type SelectionResolver struct{} @@ -20,13 +20,13 @@ func (r *SelectionResolver) Query_events(ctx context.Context) ([]Event, error) { fieldSelections := graphql.GetResolverContext(ctx).Field.Selections for _, sel := range fieldSelections { switch sel := sel.(type) { - case *query.Field: - sels = append(sels, fmt.Sprintf("%s as %s", sel.Name.Name, sel.Alias.Name)) - case *query.InlineFragment: - sels = append(sels, fmt.Sprintf("inline fragment on %s", sel.On.Name)) - case *query.FragmentSpread: - fragment := reqCtx.Doc.Fragments.Get(sel.Name.Name) - sels = append(sels, fmt.Sprintf("named fragment %s on %s", sel.Name.Name, fragment.On.Name)) + case *ast.Field: + sels = append(sels, fmt.Sprintf("%s as %s", sel.Name, sel.Alias)) + case *ast.InlineFragment: + sels = append(sels, fmt.Sprintf("inline fragment on %s", sel.TypeCondition)) + case *ast.FragmentSpread: + fragment := reqCtx.Doc.Fragments.ForName(sel.Name) + sels = append(sels, fmt.Sprintf("named fragment %s on %s", sel.Name, fragment.TypeCondition)) } } diff --git a/example/starwars/generated.go b/example/starwars/generated.go index 387dc217a01..05e88d1504a 100644 --- a/example/starwars/generated.go +++ b/example/starwars/generated.go @@ -10,9 +10,9 @@ import ( time "time" graphql "github.com/vektah/gqlgen/graphql" - introspection "github.com/vektah/gqlgen/neelance/introspection" - query "github.com/vektah/gqlgen/neelance/query" - schema "github.com/vektah/gqlgen/neelance/schema" + introspection "github.com/vektah/gqlgen/graphql/introspection" + gqlparser "github.com/vektah/gqlparser" + ast "github.com/vektah/gqlparser/ast" ) // MakeExecutableSchema creates an ExecutableSchema from the Resolvers interface. @@ -159,15 +159,15 @@ type executableSchema struct { resolvers Resolvers } -func (e *executableSchema) Schema() *schema.Schema { +func (e *executableSchema) Schema() *ast.Schema { return parsedSchema } -func (e *executableSchema) Query(ctx context.Context, op *query.Operation) *graphql.Response { +func (e *executableSchema) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers} buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte { - data := ec._Query(ctx, op.Selections) + data := ec._Query(ctx, op.SelectionSet) var buf bytes.Buffer data.MarshalGQL(&buf) return buf.Bytes() @@ -179,11 +179,11 @@ func (e *executableSchema) Query(ctx context.Context, op *query.Operation) *grap } } -func (e *executableSchema) Mutation(ctx context.Context, op *query.Operation) *graphql.Response { +func (e *executableSchema) Mutation(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers} buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte { - data := ec._Mutation(ctx, op.Selections) + data := ec._Mutation(ctx, op.SelectionSet) var buf bytes.Buffer data.MarshalGQL(&buf) return buf.Bytes() @@ -195,7 +195,7 @@ func (e *executableSchema) Mutation(ctx context.Context, op *query.Operation) *g } } -func (e *executableSchema) Subscription(ctx context.Context, op *query.Operation) func() *graphql.Response { +func (e *executableSchema) Subscription(ctx context.Context, op *ast.OperationDefinition) func() *graphql.Response { return graphql.OneShot(graphql.ErrorResponse(ctx, "subscriptions are not supported")) } @@ -208,7 +208,7 @@ type executionContext struct { var droidImplementors = []string{"Droid", "Character"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Droid(ctx context.Context, sel []query.Selection, obj *Droid) graphql.Marshaler { +func (ec *executionContext) _Droid(ctx context.Context, sel ast.SelectionSet, obj *Droid) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, droidImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -394,7 +394,7 @@ func (ec *executionContext) _Droid_primaryFunction(ctx context.Context, field gr var friendsConnectionImplementors = []string{"FriendsConnection"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _FriendsConnection(ctx context.Context, sel []query.Selection, obj *FriendsConnection) graphql.Marshaler { +func (ec *executionContext) _FriendsConnection(ctx context.Context, sel ast.SelectionSet, obj *FriendsConnection) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, friendsConnectionImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -523,7 +523,7 @@ func (ec *executionContext) _FriendsConnection_pageInfo(ctx context.Context, fie var friendsEdgeImplementors = []string{"FriendsEdge"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _FriendsEdge(ctx context.Context, sel []query.Selection, obj *FriendsEdge) graphql.Marshaler { +func (ec *executionContext) _FriendsEdge(ctx context.Context, sel ast.SelectionSet, obj *FriendsEdge) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, friendsEdgeImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -570,7 +570,7 @@ func (ec *executionContext) _FriendsEdge_node(ctx context.Context, field graphql var humanImplementors = []string{"Human", "Character"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Human(ctx context.Context, sel []query.Selection, obj *Human) graphql.Marshaler { +func (ec *executionContext) _Human(ctx context.Context, sel ast.SelectionSet, obj *Human) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, humanImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -830,7 +830,7 @@ func (ec *executionContext) _Human_starships(ctx context.Context, field graphql. var mutationImplementors = []string{"Mutation"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Mutation(ctx context.Context, sel []query.Selection) graphql.Marshaler { +func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, mutationImplementors, ec.Variables) ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{ @@ -902,7 +902,7 @@ func (ec *executionContext) _Mutation_createReview(ctx context.Context, field gr var pageInfoImplementors = []string{"PageInfo"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _PageInfo(ctx context.Context, sel []query.Selection, obj *PageInfo) graphql.Marshaler { +func (ec *executionContext) _PageInfo(ctx context.Context, sel ast.SelectionSet, obj *PageInfo) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, pageInfoImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -962,7 +962,7 @@ func (ec *executionContext) _PageInfo_hasNextPage(ctx context.Context, field gra var queryImplementors = []string{"Query"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Query(ctx context.Context, sel []query.Selection) graphql.Marshaler { +func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, queryImplementors, ec.Variables) ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{ @@ -990,10 +990,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel []query.Selection) g out.Values[i] = ec._Query_human(ctx, field) case "starship": out.Values[i] = ec._Query_starship(ctx, field) - case "__schema": - out.Values[i] = ec._Query___schema(ctx, field) case "__type": out.Values[i] = ec._Query___type(ctx, field) + case "__schema": + out.Values[i] = ec._Query___schema(ctx, field) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -1340,20 +1340,6 @@ func (ec *executionContext) _Query_starship(ctx context.Context, field graphql.C }) } -func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { - rctx := graphql.GetResolverContext(ctx) - rctx.Object = "Query" - rctx.Args = nil - rctx.Field = field - rctx.PushField(field.Alias) - defer rctx.Pop() - res := ec.introspectSchema() - if res == nil { - return graphql.Null - } - return ec.___Schema(ctx, field.Selections, res) -} - func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { args := map[string]interface{}{} var arg0 string @@ -1379,10 +1365,24 @@ func (ec *executionContext) _Query___type(ctx context.Context, field graphql.Col return ec.___Type(ctx, field.Selections, res) } +func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { + rctx := graphql.GetResolverContext(ctx) + rctx.Object = "Query" + rctx.Args = nil + rctx.Field = field + rctx.PushField(field.Alias) + defer rctx.Pop() + res := ec.introspectSchema() + if res == nil { + return graphql.Null + } + return ec.___Schema(ctx, field.Selections, res) +} + var reviewImplementors = []string{"Review"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Review(ctx context.Context, sel []query.Selection, obj *Review) graphql.Marshaler { +func (ec *executionContext) _Review(ctx context.Context, sel ast.SelectionSet, obj *Review) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, reviewImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -1445,7 +1445,7 @@ func (ec *executionContext) _Review_time(ctx context.Context, field graphql.Coll var starshipImplementors = []string{"Starship"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Starship(ctx context.Context, sel []query.Selection, obj *Starship) graphql.Marshaler { +func (ec *executionContext) _Starship(ctx context.Context, sel ast.SelectionSet, obj *Starship) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, starshipImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -1575,7 +1575,7 @@ func (ec *executionContext) _Starship_history(ctx context.Context, field graphql var __DirectiveImplementors = []string{"__Directive"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Directive(ctx context.Context, sel []query.Selection, obj *introspection.Directive) graphql.Marshaler { +func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __DirectiveImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -1608,7 +1608,7 @@ func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -1619,11 +1619,8 @@ func (ec *executionContext) ___Directive_description(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___Directive_locations(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) graphql.Marshaler { @@ -1633,7 +1630,7 @@ func (ec *executionContext) ___Directive_locations(ctx context.Context, field gr rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Locations() + res := obj.Locations arr1 := graphql.Array{} for idx1 := range res { arr1 = append(arr1, func() graphql.Marshaler { @@ -1653,7 +1650,7 @@ func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Args() + res := obj.Args arr1 := graphql.Array{} for idx1 := range res { arr1 = append(arr1, func() graphql.Marshaler { @@ -1669,7 +1666,7 @@ func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql var __EnumValueImplementors = []string{"__EnumValue"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___EnumValue(ctx context.Context, sel []query.Selection, obj *introspection.EnumValue) graphql.Marshaler { +func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __EnumValueImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -1702,7 +1699,7 @@ func (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -1713,11 +1710,8 @@ func (ec *executionContext) ___EnumValue_description(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) graphql.Marshaler { @@ -1727,7 +1721,7 @@ func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.IsDeprecated() + res := obj.IsDeprecated return graphql.MarshalBoolean(res) } @@ -1738,17 +1732,14 @@ func (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.DeprecationReason() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.DeprecationReason + return graphql.MarshalString(res) } var __FieldImplementors = []string{"__Field"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Field(ctx context.Context, sel []query.Selection, obj *introspection.Field) graphql.Marshaler { +func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __FieldImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -1785,7 +1776,7 @@ func (ec *executionContext) ___Field_name(ctx context.Context, field graphql.Col rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -1796,11 +1787,8 @@ func (ec *executionContext) ___Field_description(ctx context.Context, field grap rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) graphql.Marshaler { @@ -1810,7 +1798,7 @@ func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.Col rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Args() + res := obj.Args arr1 := graphql.Array{} for idx1 := range res { arr1 = append(arr1, func() graphql.Marshaler { @@ -1830,8 +1818,11 @@ func (ec *executionContext) ___Field_type(ctx context.Context, field graphql.Col rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Type() - return ec.___Type(ctx, field.Selections, &res) + res := obj.Type + if res == nil { + return graphql.Null + } + return ec.___Type(ctx, field.Selections, res) } func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) graphql.Marshaler { @@ -1841,7 +1832,7 @@ func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field gra rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.IsDeprecated() + res := obj.IsDeprecated return graphql.MarshalBoolean(res) } @@ -1852,17 +1843,14 @@ func (ec *executionContext) ___Field_deprecationReason(ctx context.Context, fiel rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.DeprecationReason() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.DeprecationReason + return graphql.MarshalString(res) } var __InputValueImplementors = []string{"__InputValue"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___InputValue(ctx context.Context, sel []query.Selection, obj *introspection.InputValue) graphql.Marshaler { +func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __InputValueImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -1895,7 +1883,7 @@ func (ec *executionContext) ___InputValue_name(ctx context.Context, field graphq rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -1906,11 +1894,8 @@ func (ec *executionContext) ___InputValue_description(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) graphql.Marshaler { @@ -1920,8 +1905,11 @@ func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphq rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Type() - return ec.___Type(ctx, field.Selections, &res) + res := obj.Type + if res == nil { + return graphql.Null + } + return ec.___Type(ctx, field.Selections, res) } func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) graphql.Marshaler { @@ -1931,17 +1919,14 @@ func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, fiel rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.DefaultValue() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.DefaultValue + return graphql.MarshalString(res) } var __SchemaImplementors = []string{"__Schema"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Schema(ctx context.Context, sel []query.Selection, obj *introspection.Schema) graphql.Marshaler { +func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __SchemaImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -1997,7 +1982,10 @@ func (ec *executionContext) ___Schema_queryType(ctx context.Context, field graph rctx.PushField(field.Alias) defer rctx.Pop() res := obj.QueryType() - return ec.___Type(ctx, field.Selections, &res) + if res == nil { + return graphql.Null + } + return ec.___Type(ctx, field.Selections, res) } func (ec *executionContext) ___Schema_mutationType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) graphql.Marshaler { @@ -2051,7 +2039,7 @@ func (ec *executionContext) ___Schema_directives(ctx context.Context, field grap var __TypeImplementors = []string{"__Type"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Type(ctx context.Context, sel []query.Selection, obj *introspection.Type) graphql.Marshaler { +func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __TypeImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -2106,10 +2094,7 @@ func (ec *executionContext) ___Type_name(ctx context.Context, field graphql.Coll rctx.PushField(field.Alias) defer rctx.Pop() res := obj.Name() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + return graphql.MarshalString(res) } func (ec *executionContext) ___Type_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) graphql.Marshaler { @@ -2120,10 +2105,7 @@ func (ec *executionContext) ___Type_description(ctx context.Context, field graph rctx.PushField(field.Alias) defer rctx.Pop() res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + return graphql.MarshalString(res) } func (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) graphql.Marshaler { @@ -2262,7 +2244,7 @@ func (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.Co return ec.___Type(ctx, field.Selections, res) } -func (ec *executionContext) _Character(ctx context.Context, sel []query.Selection, obj *Character) graphql.Marshaler { +func (ec *executionContext) _Character(ctx context.Context, sel ast.SelectionSet, obj *Character) graphql.Marshaler { switch obj := (*obj).(type) { case nil: return graphql.Null @@ -2279,7 +2261,7 @@ func (ec *executionContext) _Character(ctx context.Context, sel []query.Selectio } } -func (ec *executionContext) _SearchResult(ctx context.Context, sel []query.Selection, obj *SearchResult) graphql.Marshaler { +func (ec *executionContext) _SearchResult(ctx context.Context, sel ast.SelectionSet, obj *SearchResult) graphql.Marshaler { switch obj := (*obj).(type) { case nil: return graphql.Null @@ -2340,14 +2322,10 @@ func (ec *executionContext) introspectSchema() *introspection.Schema { } func (ec *executionContext) introspectType(name string) *introspection.Type { - t := parsedSchema.Resolve(name) - if t == nil { - return nil - } - return introspection.WrapType(t) + return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]) } -var parsedSchema = schema.MustParse(`# The query type, represents all of the entry points into our object graph +var parsedSchema = gqlparser.MustLoadSchema(introspection.Prelude + `# The query type, represents all of the entry points into our object graph type Query { hero(episode: Episode = NEWHOPE): Character reviews(episode: Episode!, since: Time): [Review!]! diff --git a/example/starwars/models_gen.go b/example/starwars/models_gen.go index e42aa8ef9cd..d72bb8103a9 100644 --- a/example/starwars/models_gen.go +++ b/example/starwars/models_gen.go @@ -29,9 +29,8 @@ type Starship struct { type Episode string const ( - // Star Wars Episode IV: A New Hope, released in 1977. - EpisodeNewhope Episode = "NEWHOPE" // Star Wars Episode V: The Empire Strikes Back, released in 1980. - EpisodeEmpire Episode = "EMPIRE" // Star Wars Episode VI: Return of the Jedi, released in 1983. + EpisodeNewhope Episode = "NEWHOPE" + EpisodeEmpire Episode = "EMPIRE" EpisodeJedi Episode = "JEDI" ) @@ -67,8 +66,7 @@ func (e Episode) MarshalGQL(w io.Writer) { type LengthUnit string const ( - // The standard unit around the world - LengthUnitMeter LengthUnit = "METER" // Primarily used in the United States + LengthUnitMeter LengthUnit = "METER" LengthUnitFoot LengthUnit = "FOOT" ) diff --git a/example/starwars/starwars_test.go b/example/starwars/starwars_test.go index 53cc7b32dd6..8fbb54547bf 100644 --- a/example/starwars/starwars_test.go +++ b/example/starwars/starwars_test.go @@ -6,8 +6,8 @@ import ( "github.com/stretchr/testify/require" "github.com/vektah/gqlgen/client" + "github.com/vektah/gqlgen/graphql/introspection" "github.com/vektah/gqlgen/handler" - introspection "github.com/vektah/gqlgen/neelance/introspection" ) func TestStarwars(t *testing.T) { @@ -31,7 +31,7 @@ func TestStarwars(t *testing.T) { Typename string `json:"__typename"` } } - c.MustPost(`{ character(id:2001) { name, __typename } }`, &resp) + c.MustPost(`{ character(id:"2001") { name, __typename } }`, &resp) require.Equal(t, "R2-D2", resp.Character.Name) require.Equal(t, "Droid", resp.Character.Typename) @@ -41,7 +41,7 @@ func TestStarwars(t *testing.T) { var resp struct { Character *struct{ Name string } } - c.MustPost(`{ character(id:2002) { name } }`, &resp) + c.MustPost(`{ character(id:"2002") { name } }`, &resp) require.Nil(t, resp.Character) }) @@ -50,7 +50,7 @@ func TestStarwars(t *testing.T) { var resp struct { Droid struct{ PrimaryFunction string } } - c.MustPost(`{ droid(id:2001) { primaryFunction } }`, &resp) + c.MustPost(`{ droid(id:"2001") { primaryFunction } }`, &resp) require.Equal(t, "Astromech", resp.Droid.PrimaryFunction) }) @@ -64,7 +64,7 @@ func TestStarwars(t *testing.T) { } } } - c.MustPost(`{ human(id:1000) { starships { name length(unit:FOOT) } } }`, &resp) + c.MustPost(`{ human(id:"1000") { starships { name length(unit:FOOT) } } }`, &resp) require.Equal(t, "X-Wing", resp.Human.Starships[0].Name) require.Equal(t, 41.0105, resp.Human.Starships[0].Length) @@ -103,7 +103,7 @@ func TestStarwars(t *testing.T) { } } } - c.MustPost(`{ human(id: 1001) { friends { name } } }`, &resp) + c.MustPost(`{ human(id: "1001") { friends { name } } }`, &resp) require.Equal(t, "Wilhuff Tarkin", resp.Human.Friends[0].Name) }) @@ -118,7 +118,7 @@ func TestStarwars(t *testing.T) { } } } - c.MustPost(`{ droid(id:2001) { friendsConnection { friends { name } } } }`, &resp) + c.MustPost(`{ droid(id:"2001") { friendsConnection { friends { name } } } }`, &resp) require.Equal(t, "Luke Skywalker", resp.Droid.FriendsConnection.Friends[0].Name) require.Equal(t, "Han Solo", resp.Droid.FriendsConnection.Friends[1].Name) @@ -138,7 +138,7 @@ func TestStarwars(t *testing.T) { } } } - c.MustPost(`{ droid(id:2001) { friendsConnection { edges { cursor, node { name } } } } }`, &resp) + c.MustPost(`{ droid(id:"2001") { friendsConnection { edges { cursor, node { name } } } } }`, &resp) require.Equal(t, "Y3Vyc29yMQ==", resp.Droid.FriendsConnection.Edges[0].Cursor) require.Equal(t, "Luke Skywalker", resp.Droid.FriendsConnection.Edges[0].Node.Name) @@ -234,8 +234,8 @@ func TestStarwars(t *testing.T) { } } c.MustPost(`{ - character(id: 2001) { name } - aliasedCharacter: character(id: 2001) { name } + character(id: "2001") { name } + aliasedCharacter: character(id: "2001") { name } }`, &resp) require.Equal(t, resp.Character, resp.AliasedCharacter) }) diff --git a/example/todo/generated.go b/example/todo/generated.go index 5128534d4d2..f93030fa540 100644 --- a/example/todo/generated.go +++ b/example/todo/generated.go @@ -8,9 +8,9 @@ import ( strconv "strconv" graphql "github.com/vektah/gqlgen/graphql" - introspection "github.com/vektah/gqlgen/neelance/introspection" - query "github.com/vektah/gqlgen/neelance/query" - schema "github.com/vektah/gqlgen/neelance/schema" + introspection "github.com/vektah/gqlgen/graphql/introspection" + gqlparser "github.com/vektah/gqlparser" + ast "github.com/vektah/gqlparser/ast" ) // MakeExecutableSchema creates an ExecutableSchema from the Resolvers interface. @@ -73,15 +73,15 @@ type executableSchema struct { resolvers Resolvers } -func (e *executableSchema) Schema() *schema.Schema { +func (e *executableSchema) Schema() *ast.Schema { return parsedSchema } -func (e *executableSchema) Query(ctx context.Context, op *query.Operation) *graphql.Response { +func (e *executableSchema) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers} buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte { - data := ec._MyQuery(ctx, op.Selections) + data := ec._MyQuery(ctx, op.SelectionSet) var buf bytes.Buffer data.MarshalGQL(&buf) return buf.Bytes() @@ -93,11 +93,11 @@ func (e *executableSchema) Query(ctx context.Context, op *query.Operation) *grap } } -func (e *executableSchema) Mutation(ctx context.Context, op *query.Operation) *graphql.Response { +func (e *executableSchema) Mutation(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers} buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte { - data := ec._MyMutation(ctx, op.Selections) + data := ec._MyMutation(ctx, op.SelectionSet) var buf bytes.Buffer data.MarshalGQL(&buf) return buf.Bytes() @@ -109,7 +109,7 @@ func (e *executableSchema) Mutation(ctx context.Context, op *query.Operation) *g } } -func (e *executableSchema) Subscription(ctx context.Context, op *query.Operation) func() *graphql.Response { +func (e *executableSchema) Subscription(ctx context.Context, op *ast.OperationDefinition) func() *graphql.Response { return graphql.OneShot(graphql.ErrorResponse(ctx, "subscriptions are not supported")) } @@ -122,7 +122,7 @@ type executionContext struct { var myMutationImplementors = []string{"MyMutation"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _MyMutation(ctx context.Context, sel []query.Selection) graphql.Marshaler { +func (ec *executionContext) _MyMutation(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, myMutationImplementors, ec.Variables) ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{ @@ -228,7 +228,7 @@ func (ec *executionContext) _MyMutation_updateTodo(ctx context.Context, field gr var myQueryImplementors = []string{"MyQuery"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _MyQuery(ctx context.Context, sel []query.Selection) graphql.Marshaler { +func (ec *executionContext) _MyQuery(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, myQueryImplementors, ec.Variables) ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{ @@ -248,10 +248,10 @@ func (ec *executionContext) _MyQuery(ctx context.Context, sel []query.Selection) out.Values[i] = ec._MyQuery_lastTodo(ctx, field) case "todos": out.Values[i] = ec._MyQuery_todos(ctx, field) - case "__schema": - out.Values[i] = ec._MyQuery___schema(ctx, field) case "__type": out.Values[i] = ec._MyQuery___type(ctx, field) + case "__schema": + out.Values[i] = ec._MyQuery___schema(ctx, field) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -376,20 +376,6 @@ func (ec *executionContext) _MyQuery_todos(ctx context.Context, field graphql.Co }) } -func (ec *executionContext) _MyQuery___schema(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { - rctx := graphql.GetResolverContext(ctx) - rctx.Object = "MyQuery" - rctx.Args = nil - rctx.Field = field - rctx.PushField(field.Alias) - defer rctx.Pop() - res := ec.introspectSchema() - if res == nil { - return graphql.Null - } - return ec.___Schema(ctx, field.Selections, res) -} - func (ec *executionContext) _MyQuery___type(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { args := map[string]interface{}{} var arg0 string @@ -415,10 +401,24 @@ func (ec *executionContext) _MyQuery___type(ctx context.Context, field graphql.C return ec.___Type(ctx, field.Selections, res) } +func (ec *executionContext) _MyQuery___schema(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { + rctx := graphql.GetResolverContext(ctx) + rctx.Object = "MyQuery" + rctx.Args = nil + rctx.Field = field + rctx.PushField(field.Alias) + defer rctx.Pop() + res := ec.introspectSchema() + if res == nil { + return graphql.Null + } + return ec.___Schema(ctx, field.Selections, res) +} + var todoImplementors = []string{"Todo"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Todo(ctx context.Context, sel []query.Selection, obj *Todo) graphql.Marshaler { +func (ec *executionContext) _Todo(ctx context.Context, sel ast.SelectionSet, obj *Todo) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, todoImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -478,7 +478,7 @@ func (ec *executionContext) _Todo_done(ctx context.Context, field graphql.Collec var __DirectiveImplementors = []string{"__Directive"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Directive(ctx context.Context, sel []query.Selection, obj *introspection.Directive) graphql.Marshaler { +func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __DirectiveImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -511,7 +511,7 @@ func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -522,11 +522,8 @@ func (ec *executionContext) ___Directive_description(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___Directive_locations(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) graphql.Marshaler { @@ -536,7 +533,7 @@ func (ec *executionContext) ___Directive_locations(ctx context.Context, field gr rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Locations() + res := obj.Locations arr1 := graphql.Array{} for idx1 := range res { arr1 = append(arr1, func() graphql.Marshaler { @@ -556,7 +553,7 @@ func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Args() + res := obj.Args arr1 := graphql.Array{} for idx1 := range res { arr1 = append(arr1, func() graphql.Marshaler { @@ -572,7 +569,7 @@ func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql var __EnumValueImplementors = []string{"__EnumValue"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___EnumValue(ctx context.Context, sel []query.Selection, obj *introspection.EnumValue) graphql.Marshaler { +func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __EnumValueImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -605,7 +602,7 @@ func (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -616,11 +613,8 @@ func (ec *executionContext) ___EnumValue_description(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) graphql.Marshaler { @@ -630,7 +624,7 @@ func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.IsDeprecated() + res := obj.IsDeprecated return graphql.MarshalBoolean(res) } @@ -641,17 +635,14 @@ func (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.DeprecationReason() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.DeprecationReason + return graphql.MarshalString(res) } var __FieldImplementors = []string{"__Field"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Field(ctx context.Context, sel []query.Selection, obj *introspection.Field) graphql.Marshaler { +func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __FieldImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -688,7 +679,7 @@ func (ec *executionContext) ___Field_name(ctx context.Context, field graphql.Col rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -699,11 +690,8 @@ func (ec *executionContext) ___Field_description(ctx context.Context, field grap rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) graphql.Marshaler { @@ -713,7 +701,7 @@ func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.Col rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Args() + res := obj.Args arr1 := graphql.Array{} for idx1 := range res { arr1 = append(arr1, func() graphql.Marshaler { @@ -733,8 +721,11 @@ func (ec *executionContext) ___Field_type(ctx context.Context, field graphql.Col rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Type() - return ec.___Type(ctx, field.Selections, &res) + res := obj.Type + if res == nil { + return graphql.Null + } + return ec.___Type(ctx, field.Selections, res) } func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) graphql.Marshaler { @@ -744,7 +735,7 @@ func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field gra rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.IsDeprecated() + res := obj.IsDeprecated return graphql.MarshalBoolean(res) } @@ -755,17 +746,14 @@ func (ec *executionContext) ___Field_deprecationReason(ctx context.Context, fiel rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.DeprecationReason() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.DeprecationReason + return graphql.MarshalString(res) } var __InputValueImplementors = []string{"__InputValue"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___InputValue(ctx context.Context, sel []query.Selection, obj *introspection.InputValue) graphql.Marshaler { +func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __InputValueImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -798,7 +786,7 @@ func (ec *executionContext) ___InputValue_name(ctx context.Context, field graphq rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -809,11 +797,8 @@ func (ec *executionContext) ___InputValue_description(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) graphql.Marshaler { @@ -823,8 +808,11 @@ func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphq rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Type() - return ec.___Type(ctx, field.Selections, &res) + res := obj.Type + if res == nil { + return graphql.Null + } + return ec.___Type(ctx, field.Selections, res) } func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) graphql.Marshaler { @@ -834,17 +822,14 @@ func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, fiel rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.DefaultValue() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.DefaultValue + return graphql.MarshalString(res) } var __SchemaImplementors = []string{"__Schema"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Schema(ctx context.Context, sel []query.Selection, obj *introspection.Schema) graphql.Marshaler { +func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __SchemaImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -900,7 +885,10 @@ func (ec *executionContext) ___Schema_queryType(ctx context.Context, field graph rctx.PushField(field.Alias) defer rctx.Pop() res := obj.QueryType() - return ec.___Type(ctx, field.Selections, &res) + if res == nil { + return graphql.Null + } + return ec.___Type(ctx, field.Selections, res) } func (ec *executionContext) ___Schema_mutationType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) graphql.Marshaler { @@ -954,7 +942,7 @@ func (ec *executionContext) ___Schema_directives(ctx context.Context, field grap var __TypeImplementors = []string{"__Type"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Type(ctx context.Context, sel []query.Selection, obj *introspection.Type) graphql.Marshaler { +func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __TypeImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -1009,10 +997,7 @@ func (ec *executionContext) ___Type_name(ctx context.Context, field graphql.Coll rctx.PushField(field.Alias) defer rctx.Pop() res := obj.Name() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + return graphql.MarshalString(res) } func (ec *executionContext) ___Type_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) graphql.Marshaler { @@ -1023,10 +1008,7 @@ func (ec *executionContext) ___Type_description(ctx context.Context, field graph rctx.PushField(field.Alias) defer rctx.Pop() res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + return graphql.MarshalString(res) } func (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) graphql.Marshaler { @@ -1199,14 +1181,10 @@ func (ec *executionContext) introspectSchema() *introspection.Schema { } func (ec *executionContext) introspectType(name string) *introspection.Type { - t := parsedSchema.Resolve(name) - if t == nil { - return nil - } - return introspection.WrapType(t) + return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]) } -var parsedSchema = schema.MustParse(`schema { +var parsedSchema = gqlparser.MustLoadSchema(introspection.Prelude + `schema { query: MyQuery mutation: MyMutation } diff --git a/example/todo/todo.go b/example/todo/todo.go index edcfee356e3..4d95fcc1040 100644 --- a/example/todo/todo.go +++ b/example/todo/todo.go @@ -1,4 +1,4 @@ -//go:generate gorunpkg github.com/vektah/gqlgen -out generated.go +//go:generate gorunpkg github.com/vektah/gqlgen -out generated.go -v package todo diff --git a/example/todo/todo_test.go b/example/todo/todo_test.go index bdb9e9d4542..a9bcbe42e15 100644 --- a/example/todo/todo_test.go +++ b/example/todo/todo_test.go @@ -6,8 +6,8 @@ import ( "github.com/stretchr/testify/require" "github.com/vektah/gqlgen/client" + introspection "github.com/vektah/gqlgen/graphql/introspection" "github.com/vektah/gqlgen/handler" - "github.com/vektah/gqlgen/neelance/introspection" ) func TestTodo(t *testing.T) { diff --git a/graphql/context.go b/graphql/context.go index 8f544100162..adce8491c3f 100644 --- a/graphql/context.go +++ b/graphql/context.go @@ -5,7 +5,8 @@ import ( "fmt" "sync" - "github.com/vektah/gqlgen/neelance/query" + "github.com/vektah/gqlparser/ast" + "github.com/vektah/gqlparser/gqlerror" ) type Resolver func(ctx context.Context) (res interface{}, err error) @@ -15,7 +16,7 @@ type RequestMiddleware func(ctx context.Context, next func(ctx context.Context) type RequestContext struct { RawQuery string Variables map[string]interface{} - Doc *query.Document + Doc *ast.QueryDocument // ErrorPresenter will be used to generate the error // message from errors given to Error(). ErrorPresenter ErrorPresenterFunc @@ -24,7 +25,7 @@ type RequestContext struct { RequestMiddleware RequestMiddleware errorsMu sync.Mutex - Errors []*Error + Errors gqlerror.List } func DefaultResolverMiddleware(ctx context.Context, next Resolver) (res interface{}, err error) { @@ -35,7 +36,7 @@ func DefaultRequestMiddleware(ctx context.Context, next func(ctx context.Context return next(ctx) } -func NewRequestContext(doc *query.Document, query string, variables map[string]interface{}) *RequestContext { +func NewRequestContext(doc *ast.QueryDocument, query string, variables map[string]interface{}) *RequestContext { return &RequestContext{ Doc: doc, RawQuery: query, diff --git a/graphql/error.go b/graphql/error.go index 15e65fabab9..58f409c33f1 100644 --- a/graphql/error.go +++ b/graphql/error.go @@ -2,33 +2,18 @@ package graphql import ( "context" -) - -// Error is the standard graphql error type described in https://facebook.github.io/graphql/draft/#sec-Errors -type Error struct { - Message string `json:"message"` - Path []interface{} `json:"path,omitempty"` - Locations []ErrorLocation `json:"locations,omitempty"` - Extensions map[string]interface{} `json:"extensions,omitempty"` -} -func (e *Error) Error() string { - return e.Message -} - -type ErrorLocation struct { - Line int `json:"line,omitempty"` - Column int `json:"column,omitempty"` -} + "github.com/vektah/gqlparser/gqlerror" +) -type ErrorPresenterFunc func(context.Context, error) *Error +type ErrorPresenterFunc func(context.Context, error) *gqlerror.Error type ExtendedError interface { Extensions() map[string]interface{} } -func DefaultErrorPresenter(ctx context.Context, err error) *Error { - if gqlerr, ok := err.(*Error); ok { +func DefaultErrorPresenter(ctx context.Context, err error) *gqlerror.Error { + if gqlerr, ok := err.(*gqlerror.Error); ok { gqlerr.Path = GetResolverContext(ctx).Path return gqlerr } @@ -38,7 +23,7 @@ func DefaultErrorPresenter(ctx context.Context, err error) *Error { extensions = ee.Extensions() } - return &Error{ + return &gqlerror.Error{ Message: err.Error(), Path: GetResolverContext(ctx).Path, Extensions: extensions, diff --git a/graphql/exec.go b/graphql/exec.go index 2c034888bba..0610b397a5a 100644 --- a/graphql/exec.go +++ b/graphql/exec.go @@ -4,78 +4,80 @@ import ( "context" "fmt" - "github.com/vektah/gqlgen/neelance/common" - "github.com/vektah/gqlgen/neelance/query" - "github.com/vektah/gqlgen/neelance/schema" + "github.com/vektah/gqlparser/ast" ) type ExecutableSchema interface { - Schema() *schema.Schema + Schema() *ast.Schema - Query(ctx context.Context, op *query.Operation) *Response - Mutation(ctx context.Context, op *query.Operation) *Response - Subscription(ctx context.Context, op *query.Operation) func() *Response + Query(ctx context.Context, op *ast.OperationDefinition) *Response + Mutation(ctx context.Context, op *ast.OperationDefinition) *Response + Subscription(ctx context.Context, op *ast.OperationDefinition) func() *Response } -func CollectFields(doc *query.Document, selSet []query.Selection, satisfies []string, variables map[string]interface{}) []CollectedField { +func CollectFields(doc *ast.QueryDocument, selSet ast.SelectionSet, satisfies []string, variables map[string]interface{}) []CollectedField { return collectFields(doc, selSet, satisfies, variables, map[string]bool{}) } -func collectFields(doc *query.Document, selSet []query.Selection, satisfies []string, variables map[string]interface{}, visited map[string]bool) []CollectedField { +func collectFields(doc *ast.QueryDocument, selSet ast.SelectionSet, satisfies []string, variables map[string]interface{}, visited map[string]bool) []CollectedField { var groupedFields []CollectedField for _, sel := range selSet { switch sel := sel.(type) { - case *query.Field: - f := getOrCreateField(&groupedFields, sel.Alias.Name, func() CollectedField { + case *ast.Field: + f := getOrCreateField(&groupedFields, sel.Alias, func() CollectedField { f := CollectedField{ - Alias: sel.Alias.Name, - Name: sel.Name.Name, + Alias: sel.Alias, + Name: sel.Name, } if len(sel.Arguments) > 0 { f.Args = map[string]interface{}{} for _, arg := range sel.Arguments { - if variable, ok := arg.Value.(*common.Variable); ok { - if val, ok := variables[variable.Name]; ok { - f.Args[arg.Name.Name] = val + if arg.Value.Kind == ast.Variable { + if val, ok := variables[arg.Value.Raw]; ok { + f.Args[arg.Name] = val } } else { - f.Args[arg.Name.Name] = arg.Value.Value(variables) + var err error + f.Args[arg.Name], err = arg.Value.Value(variables) + if err != nil { + panic(err) + } } } } return f }) - f.Selections = append(f.Selections, sel.Selections...) - case *query.InlineFragment: - if !instanceOf(sel.On.Ident.Name, satisfies) { + f.Selections = append(f.Selections, sel.SelectionSet...) + case *ast.InlineFragment: + if !instanceOf(sel.TypeCondition, satisfies) { continue } - for _, childField := range collectFields(doc, sel.Selections, satisfies, variables, visited) { + for _, childField := range collectFields(doc, sel.SelectionSet, satisfies, variables, visited) { f := getOrCreateField(&groupedFields, childField.Name, func() CollectedField { return childField }) f.Selections = append(f.Selections, childField.Selections...) } - case *query.FragmentSpread: - fragmentName := sel.Name.Name + case *ast.FragmentSpread: + fragmentName := sel.Name if _, seen := visited[fragmentName]; seen { continue } visited[fragmentName] = true - fragment := doc.Fragments.Get(fragmentName) + fragment := doc.Fragments.ForName(fragmentName) if fragment == nil { // should never happen, validator has already run panic(fmt.Errorf("missing fragment %s", fragmentName)) } - if !instanceOf(fragment.On.Ident.Name, satisfies) { + if !instanceOf(fragment.TypeCondition, satisfies) { continue } - for _, childField := range collectFields(doc, fragment.Selections, satisfies, variables, visited) { + for _, childField := range collectFields(doc, fragment.SelectionSet, satisfies, variables, visited) { f := getOrCreateField(&groupedFields, childField.Name, func() CollectedField { return childField }) f.Selections = append(f.Selections, childField.Selections...) } @@ -92,7 +94,7 @@ type CollectedField struct { Alias string Name string Args map[string]interface{} - Selections []query.Selection + Selections ast.SelectionSet } func instanceOf(val string, satisfies []string) bool { diff --git a/graphql/int.go b/graphql/int.go index b63b4c2aa66..6b2da63a1b8 100644 --- a/graphql/int.go +++ b/graphql/int.go @@ -18,6 +18,8 @@ func UnmarshalInt(v interface{}) (int, error) { return strconv.Atoi(v) case int: return v, nil + case int64: + return int(v), nil case float64: return int(v), nil default: diff --git a/graphql/introspection/inliner/inliner.go b/graphql/introspection/inliner/inliner.go new file mode 100644 index 00000000000..06caaf19434 --- /dev/null +++ b/graphql/introspection/inliner/inliner.go @@ -0,0 +1,31 @@ +package main + +import ( + "bytes" + "io/ioutil" + + "strconv" + + "golang.org/x/tools/imports" +) + +func main() { + out := bytes.Buffer{} + out.WriteString("package introspection\n\n") + out.WriteString("var Prelude = ") + + file, err := ioutil.ReadFile("prelude.graphql") + if err != nil { + panic(err) + } + + out.WriteString(strconv.Quote(string(file))) + out.WriteString("\n") + + formatted, err2 := imports.Process("prelude.go", out.Bytes(), nil) + if err2 != nil { + panic(err2) + } + + ioutil.WriteFile("prelude.go", formatted, 0644) +} diff --git a/graphql/introspection/introspection.go b/graphql/introspection/introspection.go new file mode 100644 index 00000000000..80682f58460 --- /dev/null +++ b/graphql/introspection/introspection.go @@ -0,0 +1,60 @@ +//go:generate go run ./inliner/inliner.go + +// introspection implements the spec defined in https://github.com/facebook/graphql/blob/master/spec/Section%204%20--%20Introspection.md#schema-introspection +package introspection + +import "github.com/vektah/gqlparser/ast" + +type ( + Directive struct { + Name string + Description string + Locations []string + Args []InputValue + } + + EnumValue struct { + Name string + Description string + IsDeprecated bool + DeprecationReason string + } + + Field struct { + Name string + Description string + Type *Type + Args []InputValue + IsDeprecated bool + DeprecationReason string + } + + InputValue struct { + Name string + Description string + DefaultValue string + Type *Type + } +) + +func WrapSchema(schema *ast.Schema) *Schema { + return &Schema{schema: schema} +} + +func isDeprecated(directives ast.DirectiveList) bool { + return directives.ForName("deprecated") != nil +} + +func deprecationReason(directives ast.DirectiveList) string { + deprecation := directives.ForName("deprecated") + if deprecation == nil { + return "" + } + + reason := deprecation.Arguments.ForName("reason") + if reason == nil { + return "" + } + + return reason.Value.Raw +} diff --git a/graphql/introspection/prelude.go b/graphql/introspection/prelude.go new file mode 100644 index 00000000000..ef45909d9b1 --- /dev/null +++ b/graphql/introspection/prelude.go @@ -0,0 +1,3 @@ +package introspection + +var Prelude = "# The `Map` scalar type is a simple json object\nscalar Map\n\ntype __Schema {\n types: [__Type!]!\n queryType: __Type!\n mutationType: __Type\n subscriptionType: __Type\n directives: [__Directive!]!\n}\n\ntype __Type {\n kind: __TypeKind!\n name: String\n description: String\n\n # OBJECT and INTERFACE only\n fields(includeDeprecated: Boolean = false): [__Field!]\n\n # OBJECT only\n interfaces: [__Type!]\n\n # INTERFACE and UNION only\n possibleTypes: [__Type!]\n\n # ENUM only\n enumValues(includeDeprecated: Boolean = false): [__EnumValue!]\n\n # INPUT_OBJECT only\n inputFields: [__InputValue!]\n\n # NON_NULL and LIST only\n ofType: __Type\n}\n\ntype __Field {\n name: String!\n description: String\n args: [__InputValue!]!\n type: __Type!\n isDeprecated: Boolean!\n deprecationReason: String\n}\n\ntype __InputValue {\n name: String!\n description: String\n type: __Type!\n defaultValue: String\n}\n\ntype __EnumValue {\n name: String!\n description: String\n isDeprecated: Boolean!\n deprecationReason: String\n}\n\nenum __TypeKind {\n SCALAR\n OBJECT\n INTERFACE\n UNION\n ENUM\n INPUT_OBJECT\n LIST\n NON_NULL\n}\n\ntype __Directive {\n name: String!\n description: String\n locations: [__DirectiveLocation!]!\n args: [__InputValue!]!\n}\n\nenum __DirectiveLocation {\n QUERY\n MUTATION\n SUBSCRIPTION\n FIELD\n FRAGMENT_DEFINITION\n FRAGMENT_SPREAD\n INLINE_FRAGMENT\n SCHEMA\n SCALAR\n OBJECT\n FIELD_DEFINITION\n ARGUMENT_DEFINITION\n INTERFACE\n UNION\n ENUM\n ENUM_VALUE\n INPUT_OBJECT\n INPUT_FIELD_DEFINITION\n}\n" diff --git a/graphql/introspection/prelude.graphql b/graphql/introspection/prelude.graphql new file mode 100644 index 00000000000..1ecf05ebd9c --- /dev/null +++ b/graphql/introspection/prelude.graphql @@ -0,0 +1,96 @@ +# The `Map` scalar type is a simple json object +scalar Map + +type __Schema { + types: [__Type!]! + queryType: __Type! + mutationType: __Type + subscriptionType: __Type + directives: [__Directive!]! +} + +type __Type { + kind: __TypeKind! + name: String + description: String + + # OBJECT and INTERFACE only + fields(includeDeprecated: Boolean = false): [__Field!] + + # OBJECT only + interfaces: [__Type!] + + # INTERFACE and UNION only + possibleTypes: [__Type!] + + # ENUM only + enumValues(includeDeprecated: Boolean = false): [__EnumValue!] + + # INPUT_OBJECT only + inputFields: [__InputValue!] + + # NON_NULL and LIST only + ofType: __Type +} + +type __Field { + name: String! + description: String + args: [__InputValue!]! + type: __Type! + isDeprecated: Boolean! + deprecationReason: String +} + +type __InputValue { + name: String! + description: String + type: __Type! + defaultValue: String +} + +type __EnumValue { + name: String! + description: String + isDeprecated: Boolean! + deprecationReason: String +} + +enum __TypeKind { + SCALAR + OBJECT + INTERFACE + UNION + ENUM + INPUT_OBJECT + LIST + NON_NULL +} + +type __Directive { + name: String! + description: String + locations: [__DirectiveLocation!]! + args: [__InputValue!]! +} + +enum __DirectiveLocation { + QUERY + MUTATION + SUBSCRIPTION + FIELD + FRAGMENT_DEFINITION + FRAGMENT_SPREAD + INLINE_FRAGMENT + SCHEMA + SCALAR + OBJECT + FIELD_DEFINITION + ARGUMENT_DEFINITION + INTERFACE + UNION + ENUM + ENUM_VALUE + INPUT_OBJECT + INPUT_FIELD_DEFINITION +} diff --git a/neelance/introspection/query.go b/graphql/introspection/query.go similarity index 100% rename from neelance/introspection/query.go rename to graphql/introspection/query.go diff --git a/graphql/introspection/schema.go b/graphql/introspection/schema.go new file mode 100644 index 00000000000..39e6530811f --- /dev/null +++ b/graphql/introspection/schema.go @@ -0,0 +1,43 @@ +package introspection + +import "github.com/vektah/gqlparser/ast" + +type Schema struct { + schema *ast.Schema +} + +func (s *Schema) Types() []Type { + var types []Type + for _, typ := range s.schema.Types { + types = append(types, *WrapTypeFromDef(s.schema, typ)) + } + return types +} + +func (s *Schema) QueryType() *Type { + return WrapTypeFromDef(s.schema, s.schema.Query) +} + +func (s *Schema) MutationType() *Type { + return WrapTypeFromDef(s.schema, s.schema.Query) +} + +func (s *Schema) SubscriptionType() *Type { + return WrapTypeFromDef(s.schema, s.schema.Query) +} + +func (s *Schema) Directives() []Directive { + var res []Directive + for _, d := range s.schema.Directives { + var locs []string + for _, loc := range d.Locations { + locs = append(locs, string(loc)) + } + res = append(res, Directive{ + Name: d.Name, + Description: d.Description, + Locations: locs, + }) + } + return res +} diff --git a/graphql/introspection/type.go b/graphql/introspection/type.go new file mode 100644 index 00000000000..9c65b7ee813 --- /dev/null +++ b/graphql/introspection/type.go @@ -0,0 +1,147 @@ +package introspection + +import ( + "github.com/vektah/gqlparser/ast" +) + +type Type struct { + schema *ast.Schema + def *ast.Definition + typ *ast.Type +} + +func WrapTypeFromDef(s *ast.Schema, def *ast.Definition) *Type { + if def == nil { + return nil + } + return &Type{schema: s, def: def} +} + +func WrapTypeFromType(s *ast.Schema, typ *ast.Type) *Type { + if typ == nil { + return nil + } + + if !typ.NonNull && typ.NamedType != "" { + return &Type{schema: s, def: s.Types[typ.NamedType]} + } + return &Type{schema: s, typ: typ} +} + +func (t *Type) Kind() string { + if t.def != nil { + return string(t.def.Kind) + } + + if t.typ.NonNull { + return "NOT_NULL" + } + + if t.typ.Elem != nil { + return "LIST" + } + return "UNKNOWN" +} + +func (t *Type) Name() string { + if t.def == nil { + return "" + } + return t.def.Name +} + +func (t *Type) Description() string { + if t.def == nil { + return "" + } + return t.def.Description +} + +func (t *Type) Fields(includeDeprecated bool) []Field { + if t.def == nil || (t.def.Kind != ast.Object && t.def.Kind != ast.Interface) { + return nil + } + var fields []Field + for _, f := range t.def.Fields { + fields = append(fields, Field{ + Name: f.Name, + Description: f.Description, + Type: WrapTypeFromType(t.schema, f.Type), + IsDeprecated: isDeprecated(f.Directives), + DeprecationReason: deprecationReason(f.Directives), + }) + } + return fields +} + +func (t *Type) InputFields() []InputValue { + if t.def == nil || t.def.Kind != ast.InputObject { + return nil + } + + var res []InputValue + for _, f := range t.def.Fields { + res = append(res, InputValue{ + Name: f.Name, + Description: f.Description, + Type: WrapTypeFromType(t.schema, f.Type), + }) + } + return res +} + +func (t *Type) Interfaces() []Type { + if t.def == nil || t.def.Kind != ast.Object { + return nil + } + + var res []Type + for _, intf := range t.def.Interfaces { + res = append(res, *WrapTypeFromDef(t.schema, t.schema.Types[intf])) + } + + return res +} + +func (t *Type) PossibleTypes() []Type { + if t.def == nil || (t.def.Kind != ast.Interface && t.def.Kind != ast.Union) { + return nil + } + + var res []Type + for _, pt := range t.schema.GetPossibleTypes(t.def) { + res = append(res, *WrapTypeFromDef(t.schema, pt)) + } + return res +} + +func (t *Type) EnumValues(includeDeprecated bool) []EnumValue { + if t.def == nil || t.def.Kind != ast.Enum { + return nil + } + + var res []EnumValue + for _, val := range t.def.EnumValues { + res = append(res, EnumValue{ + Name: val.Name, + Description: val.Description, + IsDeprecated: isDeprecated(val.Directives), + DeprecationReason: deprecationReason(val.Directives), + }) + } + return res +} + +func (t *Type) OfType() *Type { + if t.typ == nil { + return nil + } + if t.typ.NonNull { + // fake non null nodes + cpy := t.typ + cpy.NonNull = false + + return WrapTypeFromType(t.schema, cpy) + } + return WrapTypeFromType(t.schema, t.typ.Elem) +} diff --git a/graphql/response.go b/graphql/response.go index c0dc1c2355e..18664dca05c 100644 --- a/graphql/response.go +++ b/graphql/response.go @@ -4,15 +4,17 @@ import ( "context" "encoding/json" "fmt" + + "github.com/vektah/gqlparser/gqlerror" ) type Response struct { Data json.RawMessage `json:"data"` - Errors []*Error `json:"errors,omitempty"` + Errors gqlerror.List `json:"errors,omitempty"` } func ErrorResponse(ctx context.Context, messagef string, args ...interface{}) *Response { return &Response{ - Errors: []*Error{{Message: fmt.Sprintf(messagef, args...)}}, + Errors: gqlerror.List{{Message: fmt.Sprintf(messagef, args...)}}, } } diff --git a/handler/graphql.go b/handler/graphql.go index 4a5c61f50b0..4a2cd4837d4 100644 --- a/handler/graphql.go +++ b/handler/graphql.go @@ -9,9 +9,9 @@ import ( "github.com/gorilla/websocket" "github.com/vektah/gqlgen/graphql" - "github.com/vektah/gqlgen/neelance/errors" - "github.com/vektah/gqlgen/neelance/query" - "github.com/vektah/gqlgen/neelance/validation" + "github.com/vektah/gqlparser" + "github.com/vektah/gqlparser/ast" + "github.com/vektah/gqlparser/gqlerror" ) type params struct { @@ -28,7 +28,7 @@ type Config struct { requestHook graphql.RequestMiddleware } -func (c *Config) newRequestContext(doc *query.Document, query string, variables map[string]interface{}) *graphql.RequestContext { +func (c *Config) newRequestContext(doc *ast.QueryDocument, query string, variables map[string]interface{}) *graphql.RequestContext { reqCtx := graphql.NewRequestContext(doc, query, variables) if hook := c.recover; hook != nil { reqCtx.Recover = hook @@ -157,21 +157,15 @@ func GraphQL(exec graphql.ExecutableSchema, options ...Option) http.HandlerFunc } w.Header().Set("Content-Type", "application/json") - doc, qErr := query.Parse(reqParams.Query) - if qErr != nil { - sendError(w, http.StatusUnprocessableEntity, qErr) + doc, qErr := gqlparser.LoadQuery(exec.Schema(), reqParams.Query) + if len(qErr) > 0 { + sendError(w, http.StatusUnprocessableEntity, qErr...) return } - errs := validation.Validate(exec.Schema(), doc) - if len(errs) != 0 { - sendError(w, http.StatusUnprocessableEntity, errs...) - return - } - - op, err := doc.GetOperation(reqParams.OperationName) - if err != nil { - sendErrorf(w, http.StatusUnprocessableEntity, err.Error()) + op := doc.Operations.ForName(reqParams.OperationName) + if op == nil { + sendErrorf(w, http.StatusUnprocessableEntity, "operation %s not found", reqParams.OperationName) return } @@ -185,14 +179,14 @@ func GraphQL(exec graphql.ExecutableSchema, options ...Option) http.HandlerFunc } }() - switch op.Type { - case query.Query: + switch op.Operation { + case ast.Query: b, err := json.Marshal(exec.Query(ctx, op)) if err != nil { panic(err) } w.Write(b) - case query.Mutation: + case ast.Mutation: b, err := json.Marshal(exec.Mutation(ctx, op)) if err != nil { panic(err) @@ -204,26 +198,9 @@ func GraphQL(exec graphql.ExecutableSchema, options ...Option) http.HandlerFunc }) } -func sendError(w http.ResponseWriter, code int, errors ...*errors.QueryError) { +func sendError(w http.ResponseWriter, code int, errors ...*gqlerror.Error) { w.WriteHeader(code) - var errs []*graphql.Error - for _, err := range errors { - var locations []graphql.ErrorLocation - for _, l := range err.Locations { - fmt.Println(graphql.ErrorLocation(l)) - locations = append(locations, graphql.ErrorLocation{ - Line: l.Line, - Column: l.Column, - }) - } - - errs = append(errs, &graphql.Error{ - Message: err.Message, - Path: err.Path, - Locations: locations, - }) - } - b, err := json.Marshal(&graphql.Response{Errors: errs}) + b, err := json.Marshal(&graphql.Response{Errors: errors}) if err != nil { panic(err) } @@ -231,5 +208,5 @@ func sendError(w http.ResponseWriter, code int, errors ...*errors.QueryError) { } func sendErrorf(w http.ResponseWriter, code int, format string, args ...interface{}) { - sendError(w, code, &errors.QueryError{Message: fmt.Sprintf(format, args...)}) + sendError(w, code, &gqlerror.Error{Message: fmt.Sprintf(format, args...)}) } diff --git a/handler/graphql_test.go b/handler/graphql_test.go index 718e522cf51..9add634bd67 100644 --- a/handler/graphql_test.go +++ b/handler/graphql_test.go @@ -27,13 +27,13 @@ func TestHandlerPOST(t *testing.T) { t.Run("parse failure", func(t *testing.T) { resp := doRequest(h, "POST", "/graphql", `{"query": "!"}`) assert.Equal(t, http.StatusUnprocessableEntity, resp.Code) - assert.Equal(t, `{"data":null,"errors":[{"message":"syntax error: unexpected \"!\", expecting Ident","locations":[{"line":1,"column":1}]}]}`, resp.Body.String()) + assert.Equal(t, `{"data":null,"errors":[{"message":"Unexpected !","locations":[{"line":1,"column":1}]}]}`, resp.Body.String()) }) t.Run("validation failure", func(t *testing.T) { resp := doRequest(h, "POST", "/graphql", `{"query": "{ me { title }}"}`) assert.Equal(t, http.StatusUnprocessableEntity, resp.Code) - assert.Equal(t, `{"data":null,"errors":[{"message":"Cannot query field \"title\" on type \"User\".","locations":[{"line":1,"column":8}]}]}`, resp.Body.String()) + assert.Equal(t, `{"data":null,"errors":[{"message":"Cannot query field \"title\" on type \"User\"."}]}`, resp.Body.String()) }) t.Run("execution failure", func(t *testing.T) { @@ -61,7 +61,7 @@ func TestHandlerGET(t *testing.T) { t.Run("parse failure", func(t *testing.T) { resp := doRequest(h, "GET", "/graphql?query=!", "") assert.Equal(t, http.StatusUnprocessableEntity, resp.Code) - assert.Equal(t, `{"data":null,"errors":[{"message":"syntax error: unexpected \"!\", expecting Ident","locations":[{"line":1,"column":1}]}]}`, resp.Body.String()) + assert.Equal(t, `{"data":null,"errors":[{"message":"Unexpected !","locations":[{"line":1,"column":1}]}]}`, resp.Body.String()) }) } diff --git a/handler/stub.go b/handler/stub.go index 46b27e46427..656fc1b2a87 100644 --- a/handler/stub.go +++ b/handler/stub.go @@ -5,8 +5,8 @@ import ( "time" "github.com/vektah/gqlgen/graphql" - "github.com/vektah/gqlgen/neelance/query" - "github.com/vektah/gqlgen/neelance/schema" + "github.com/vektah/gqlparser" + "github.com/vektah/gqlparser/ast" ) type executableSchemaStub struct { @@ -14,23 +14,23 @@ type executableSchemaStub struct { var _ graphql.ExecutableSchema = &executableSchemaStub{} -func (e *executableSchemaStub) Schema() *schema.Schema { - return schema.MustParse(` +func (e *executableSchemaStub) Schema() *ast.Schema { + return gqlparser.MustLoadSchema(` schema { query: Query } type Query { me: User! } type User { name: String! } `) } -func (e *executableSchemaStub) Query(ctx context.Context, op *query.Operation) *graphql.Response { +func (e *executableSchemaStub) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { return &graphql.Response{Data: []byte(`{"name":"test"}`)} } -func (e *executableSchemaStub) Mutation(ctx context.Context, op *query.Operation) *graphql.Response { +func (e *executableSchemaStub) Mutation(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { return graphql.ErrorResponse(ctx, "mutations are not supported") } -func (e *executableSchemaStub) Subscription(ctx context.Context, op *query.Operation) func() *graphql.Response { +func (e *executableSchemaStub) Subscription(ctx context.Context, op *ast.OperationDefinition) func() *graphql.Response { return func() *graphql.Response { time.Sleep(50 * time.Millisecond) select { diff --git a/handler/websocket.go b/handler/websocket.go index e80748cad82..40f9052bbbf 100644 --- a/handler/websocket.go +++ b/handler/websocket.go @@ -10,9 +10,9 @@ import ( "github.com/gorilla/websocket" "github.com/vektah/gqlgen/graphql" - "github.com/vektah/gqlgen/neelance/errors" - "github.com/vektah/gqlgen/neelance/query" - "github.com/vektah/gqlgen/neelance/validation" + "github.com/vektah/gqlparser" + "github.com/vektah/gqlparser/ast" + "github.com/vektah/gqlparser/gqlerror" ) const ( @@ -113,7 +113,7 @@ func (c *wsConnection) run() { closer := c.active[message.ID] c.mu.Unlock() if closer == nil { - c.sendError(message.ID, errors.Errorf("%s is not running, cannot stop", message.ID)) + c.sendError(message.ID, gqlerror.Errorf("%s is not running, cannot stop", message.ID)) continue } @@ -136,30 +136,24 @@ func (c *wsConnection) subscribe(message *operationMessage) bool { return false } - doc, qErr := query.Parse(reqParams.Query) + doc, qErr := gqlparser.LoadQuery(c.exec.Schema(), reqParams.Query) if qErr != nil { - c.sendError(message.ID, qErr) + c.sendError(message.ID, qErr...) return true } - errs := validation.Validate(c.exec.Schema(), doc) - if len(errs) != 0 { - c.sendError(message.ID, errs...) - return true - } - - op, err := doc.GetOperation(reqParams.OperationName) - if err != nil { - c.sendError(message.ID, errors.Errorf("%s", err.Error())) + op := doc.Operations.ForName(reqParams.OperationName) + if op == nil { + c.sendError(message.ID, gqlerror.Errorf("operation %s not found", reqParams.OperationName)) return true } reqCtx := c.cfg.newRequestContext(doc, reqParams.Query, reqParams.Variables) ctx := graphql.WithRequestContext(c.ctx, reqCtx) - if op.Type != query.Subscription { + if op.Operation != ast.Subscription { var result *graphql.Response - if op.Type == query.Query { + if op.Operation == ast.Query { result = c.exec.Query(ctx, op) } else { result = c.exec.Mutation(ctx, op) @@ -178,7 +172,7 @@ func (c *wsConnection) subscribe(message *operationMessage) bool { defer func() { if r := recover(); r != nil { userErr := reqCtx.Recover(ctx, r) - c.sendError(message.ID, &errors.QueryError{Message: userErr.Error()}) + c.sendError(message.ID, &gqlerror.Error{Message: userErr.Error()}) } }() next := c.exec.Subscription(ctx, op) @@ -200,14 +194,14 @@ func (c *wsConnection) subscribe(message *operationMessage) bool { func (c *wsConnection) sendData(id string, response *graphql.Response) { b, err := json.Marshal(response) if err != nil { - c.sendError(id, errors.Errorf("unable to encode json response: %s", err.Error())) + c.sendError(id, gqlerror.Errorf("unable to encode json response: %s", err.Error())) return } c.write(&operationMessage{Type: dataMsg, ID: id, Payload: b}) } -func (c *wsConnection) sendError(id string, errors ...*errors.QueryError) { +func (c *wsConnection) sendError(id string, errors ...*gqlerror.Error) { var errs []error for _, err := range errors { errs = append(errs, err) @@ -220,7 +214,7 @@ func (c *wsConnection) sendError(id string, errors ...*errors.QueryError) { } func (c *wsConnection) sendConnectionError(format string, args ...interface{}) { - b, err := json.Marshal(&graphql.Error{Message: fmt.Sprintf(format, args...)}) + b, err := json.Marshal(&gqlerror.Error{Message: fmt.Sprintf(format, args...)}) if err != nil { panic(err) } diff --git a/handler/websocket_test.go b/handler/websocket_test.go index 2407cb7aab3..61f252e8c5b 100644 --- a/handler/websocket_test.go +++ b/handler/websocket_test.go @@ -85,7 +85,7 @@ func TestWebsocket(t *testing.T) { msg := readOp(c) require.Equal(t, errorMsg, msg.Type) - require.Equal(t, `[{"message":"syntax error: unexpected \"!\", expecting Ident","locations":[{"line":1,"column":1}]}]`, string(msg.Payload)) + require.Equal(t, `[{"message":"Unexpected !","locations":[{"line":1,"column":1}]}]`, string(msg.Payload)) }) t.Run("client can receive data", func(t *testing.T) { diff --git a/neelance/LICENSE b/neelance/LICENSE deleted file mode 100644 index 3907cecacf2..00000000000 --- a/neelance/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -Copyright (c) 2016 Richard Musiol. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/neelance/common/directive.go b/neelance/common/directive.go deleted file mode 100644 index 62dca47f816..00000000000 --- a/neelance/common/directive.go +++ /dev/null @@ -1,32 +0,0 @@ -package common - -type Directive struct { - Name Ident - Args ArgumentList -} - -func ParseDirectives(l *Lexer) DirectiveList { - var directives DirectiveList - for l.Peek() == '@' { - l.ConsumeToken('@') - d := &Directive{} - d.Name = l.ConsumeIdentWithLoc() - d.Name.Loc.Column-- - if l.Peek() == '(' { - d.Args = ParseArguments(l) - } - directives = append(directives, d) - } - return directives -} - -type DirectiveList []*Directive - -func (l DirectiveList) Get(name string) *Directive { - for _, d := range l { - if d.Name.Name == name { - return d - } - } - return nil -} diff --git a/neelance/common/lexer.go b/neelance/common/lexer.go deleted file mode 100644 index fdc1e62272b..00000000000 --- a/neelance/common/lexer.go +++ /dev/null @@ -1,122 +0,0 @@ -package common - -import ( - "fmt" - "text/scanner" - - "github.com/vektah/gqlgen/neelance/errors" -) - -type syntaxError string - -type Lexer struct { - sc *scanner.Scanner - next rune - descComment string -} - -type Ident struct { - Name string - Loc errors.Location -} - -func New(sc *scanner.Scanner) *Lexer { - l := &Lexer{sc: sc} - l.Consume() - return l -} - -func (l *Lexer) CatchSyntaxError(f func()) (errRes *errors.QueryError) { - defer func() { - if err := recover(); err != nil { - if err, ok := err.(syntaxError); ok { - errRes = errors.Errorf("syntax error: %s", err) - errRes.Locations = []errors.Location{l.Location()} - return - } - panic(err) - } - }() - - f() - return -} - -func (l *Lexer) Peek() rune { - return l.next -} - -func (l *Lexer) Consume() { - l.descComment = "" - for { - l.next = l.sc.Scan() - if l.next == ',' { - continue - } - if l.next == '#' { - if l.sc.Peek() == ' ' { - l.sc.Next() - } - if l.descComment != "" { - l.descComment += "\n" - } - for { - next := l.sc.Next() - if next == '\n' || next == scanner.EOF { - break - } - l.descComment += string(next) - } - continue - } - break - } -} - -func (l *Lexer) ConsumeIdent() string { - name := l.sc.TokenText() - l.ConsumeToken(scanner.Ident) - return name -} - -func (l *Lexer) ConsumeIdentWithLoc() Ident { - loc := l.Location() - name := l.sc.TokenText() - l.ConsumeToken(scanner.Ident) - return Ident{name, loc} -} - -func (l *Lexer) ConsumeKeyword(keyword string) { - if l.next != scanner.Ident || l.sc.TokenText() != keyword { - l.SyntaxError(fmt.Sprintf("unexpected %q, expecting %q", l.sc.TokenText(), keyword)) - } - l.Consume() -} - -func (l *Lexer) ConsumeLiteral() *BasicLit { - lit := &BasicLit{Type: l.next, Text: l.sc.TokenText()} - l.Consume() - return lit -} - -func (l *Lexer) ConsumeToken(expected rune) { - if l.next != expected { - l.SyntaxError(fmt.Sprintf("unexpected %q, expecting %s", l.sc.TokenText(), scanner.TokenString(expected))) - } - l.Consume() -} - -func (l *Lexer) DescComment() string { - return l.descComment -} - -func (l *Lexer) SyntaxError(message string) { - panic(syntaxError(message)) -} - -func (l *Lexer) Location() errors.Location { - return errors.Location{ - Line: l.sc.Line, - Column: l.sc.Column, - } -} diff --git a/neelance/common/literals.go b/neelance/common/literals.go deleted file mode 100644 index 55619ba0ea5..00000000000 --- a/neelance/common/literals.go +++ /dev/null @@ -1,206 +0,0 @@ -package common - -import ( - "strconv" - "strings" - "text/scanner" - - "github.com/vektah/gqlgen/neelance/errors" -) - -type Literal interface { - Value(vars map[string]interface{}) interface{} - String() string - Location() errors.Location -} - -type BasicLit struct { - Type rune - Text string - Loc errors.Location -} - -func (lit *BasicLit) Value(vars map[string]interface{}) interface{} { - switch lit.Type { - case scanner.Int: - value, err := strconv.ParseInt(lit.Text, 10, 64) - if err != nil { - panic(err) - } - return int(value) - - case scanner.Float: - value, err := strconv.ParseFloat(lit.Text, 64) - if err != nil { - panic(err) - } - return value - - case scanner.String: - value, err := strconv.Unquote(lit.Text) - if err != nil { - panic(err) - } - return value - - case scanner.Ident: - switch lit.Text { - case "true": - return true - case "false": - return false - default: - return lit.Text - } - - default: - panic("invalid literal") - } -} - -func (lit *BasicLit) String() string { - return lit.Text -} - -func (lit *BasicLit) Location() errors.Location { - return lit.Loc -} - -type ListLit struct { - Entries []Literal - Loc errors.Location -} - -func (lit *ListLit) Value(vars map[string]interface{}) interface{} { - entries := make([]interface{}, len(lit.Entries)) - for i, entry := range lit.Entries { - entries[i] = entry.Value(vars) - } - return entries -} - -func (lit *ListLit) String() string { - entries := make([]string, len(lit.Entries)) - for i, entry := range lit.Entries { - entries[i] = entry.String() - } - return "[" + strings.Join(entries, ", ") + "]" -} - -func (lit *ListLit) Location() errors.Location { - return lit.Loc -} - -type ObjectLit struct { - Fields []*ObjectLitField - Loc errors.Location -} - -type ObjectLitField struct { - Name Ident - Value Literal -} - -func (lit *ObjectLit) Value(vars map[string]interface{}) interface{} { - fields := make(map[string]interface{}, len(lit.Fields)) - for _, f := range lit.Fields { - fields[f.Name.Name] = f.Value.Value(vars) - } - return fields -} - -func (lit *ObjectLit) String() string { - entries := make([]string, 0, len(lit.Fields)) - for _, f := range lit.Fields { - entries = append(entries, f.Name.Name+": "+f.Value.String()) - } - return "{" + strings.Join(entries, ", ") + "}" -} - -func (lit *ObjectLit) Location() errors.Location { - return lit.Loc -} - -type NullLit struct { - Loc errors.Location -} - -func (lit *NullLit) Value(vars map[string]interface{}) interface{} { - return nil -} - -func (lit *NullLit) String() string { - return "null" -} - -func (lit *NullLit) Location() errors.Location { - return lit.Loc -} - -type Variable struct { - Name string - Loc errors.Location -} - -func (v Variable) Value(vars map[string]interface{}) interface{} { - return vars[v.Name] -} - -func (v Variable) String() string { - return "$" + v.Name -} - -func (v *Variable) Location() errors.Location { - return v.Loc -} - -func ParseLiteral(l *Lexer, constOnly bool) Literal { - loc := l.Location() - switch l.Peek() { - case '$': - if constOnly { - l.SyntaxError("variable not allowed") - panic("unreachable") - } - l.ConsumeToken('$') - return &Variable{l.ConsumeIdent(), loc} - - case scanner.Int, scanner.Float, scanner.String, scanner.Ident: - lit := l.ConsumeLiteral() - if lit.Type == scanner.Ident && lit.Text == "null" { - return &NullLit{loc} - } - lit.Loc = loc - return lit - case '-': - l.ConsumeToken('-') - lit := l.ConsumeLiteral() - lit.Text = "-" + lit.Text - lit.Loc = loc - return lit - case '[': - l.ConsumeToken('[') - var list []Literal - for l.Peek() != ']' { - list = append(list, ParseLiteral(l, constOnly)) - } - l.ConsumeToken(']') - return &ListLit{list, loc} - - case '{': - l.ConsumeToken('{') - var fields []*ObjectLitField - for l.Peek() != '}' { - name := l.ConsumeIdentWithLoc() - l.ConsumeToken(':') - value := ParseLiteral(l, constOnly) - fields = append(fields, &ObjectLitField{name, value}) - } - l.ConsumeToken('}') - return &ObjectLit{fields, loc} - - default: - l.SyntaxError("invalid value") - panic("unreachable") - } -} diff --git a/neelance/common/types.go b/neelance/common/types.go deleted file mode 100644 index 0bbf24ef103..00000000000 --- a/neelance/common/types.go +++ /dev/null @@ -1,80 +0,0 @@ -package common - -import ( - "github.com/vektah/gqlgen/neelance/errors" -) - -type Type interface { - Kind() string - String() string -} - -type List struct { - OfType Type -} - -type NonNull struct { - OfType Type -} - -type TypeName struct { - Ident -} - -func (*List) Kind() string { return "LIST" } -func (*NonNull) Kind() string { return "NON_NULL" } -func (*TypeName) Kind() string { panic("TypeName needs to be resolved to actual type") } - -func (t *List) String() string { return "[" + t.OfType.String() + "]" } -func (t *NonNull) String() string { return t.OfType.String() + "!" } -func (*TypeName) String() string { panic("TypeName needs to be resolved to actual type") } - -func ParseType(l *Lexer) Type { - t := parseNullType(l) - if l.Peek() == '!' { - l.ConsumeToken('!') - return &NonNull{OfType: t} - } - return t -} - -func parseNullType(l *Lexer) Type { - if l.Peek() == '[' { - l.ConsumeToken('[') - ofType := ParseType(l) - l.ConsumeToken(']') - return &List{OfType: ofType} - } - - return &TypeName{Ident: l.ConsumeIdentWithLoc()} -} - -type Resolver func(name string) Type - -func ResolveType(t Type, resolver Resolver) (Type, *errors.QueryError) { - switch t := t.(type) { - case *List: - ofType, err := ResolveType(t.OfType, resolver) - if err != nil { - return nil, err - } - return &List{OfType: ofType}, nil - case *NonNull: - ofType, err := ResolveType(t.OfType, resolver) - if err != nil { - return nil, err - } - return &NonNull{OfType: ofType}, nil - case *TypeName: - refT := resolver(t.Name) - if refT == nil { - err := errors.Errorf("Unknown type %q.", t.Name) - err.Rule = "KnownTypeNames" - err.Locations = []errors.Location{t.Loc} - return nil, err - } - return refT, nil - default: - return t, nil - } -} diff --git a/neelance/common/values.go b/neelance/common/values.go deleted file mode 100644 index 09338da8ecf..00000000000 --- a/neelance/common/values.go +++ /dev/null @@ -1,77 +0,0 @@ -package common - -import ( - "github.com/vektah/gqlgen/neelance/errors" -) - -type InputValue struct { - Name Ident - Type Type - Default Literal - Desc string - Loc errors.Location - TypeLoc errors.Location -} - -type InputValueList []*InputValue - -func (l InputValueList) Get(name string) *InputValue { - for _, v := range l { - if v.Name.Name == name { - return v - } - } - return nil -} - -func ParseInputValue(l *Lexer) *InputValue { - p := &InputValue{} - p.Loc = l.Location() - p.Desc = l.DescComment() - p.Name = l.ConsumeIdentWithLoc() - l.ConsumeToken(':') - p.TypeLoc = l.Location() - p.Type = ParseType(l) - if l.Peek() == '=' { - l.ConsumeToken('=') - p.Default = ParseLiteral(l, true) - } - return p -} - -type Argument struct { - Name Ident - Value Literal -} - -type ArgumentList []Argument - -func (l ArgumentList) Get(name string) (Literal, bool) { - for _, arg := range l { - if arg.Name.Name == name { - return arg.Value, true - } - } - return nil, false -} - -func (l ArgumentList) MustGet(name string) Literal { - value, ok := l.Get(name) - if !ok { - panic("argument not found") - } - return value -} - -func ParseArguments(l *Lexer) ArgumentList { - var args ArgumentList - l.ConsumeToken('(') - for l.Peek() != ')' { - name := l.ConsumeIdentWithLoc() - l.ConsumeToken(':') - value := ParseLiteral(l, false) - args = append(args, Argument{Name: name, Value: value}) - } - l.ConsumeToken(')') - return args -} diff --git a/neelance/errors/errors.go b/neelance/errors/errors.go deleted file mode 100644 index fdfa62024db..00000000000 --- a/neelance/errors/errors.go +++ /dev/null @@ -1,41 +0,0 @@ -package errors - -import ( - "fmt" -) - -type QueryError struct { - Message string `json:"message"` - Locations []Location `json:"locations,omitempty"` - Path []interface{} `json:"path,omitempty"` - Rule string `json:"-"` - ResolverError error `json:"-"` -} - -type Location struct { - Line int `json:"line"` - Column int `json:"column"` -} - -func (a Location) Before(b Location) bool { - return a.Line < b.Line || (a.Line == b.Line && a.Column < b.Column) -} - -func Errorf(format string, a ...interface{}) *QueryError { - return &QueryError{ - Message: fmt.Sprintf(format, a...), - } -} - -func (err *QueryError) Error() string { - if err == nil { - return "" - } - str := fmt.Sprintf("graphql: %s", err.Message) - for _, loc := range err.Locations { - str += fmt.Sprintf(" (line %d, column %d)", loc.Line, loc.Column) - } - return str -} - -var _ error = &QueryError{} diff --git a/neelance/introspection/introspection.go b/neelance/introspection/introspection.go deleted file mode 100644 index 5e354c9ac25..00000000000 --- a/neelance/introspection/introspection.go +++ /dev/null @@ -1,313 +0,0 @@ -package introspection - -import ( - "sort" - - "github.com/vektah/gqlgen/neelance/common" - "github.com/vektah/gqlgen/neelance/schema" -) - -type Schema struct { - schema *schema.Schema -} - -// WrapSchema is only used internally. -func WrapSchema(schema *schema.Schema) *Schema { - return &Schema{schema} -} - -func (r *Schema) Types() []Type { - var names []string - for name := range r.schema.Types { - names = append(names, name) - } - sort.Strings(names) - - l := make([]Type, len(names)) - for i, name := range names { - l[i] = Type{r.schema.Types[name]} - } - return l -} - -func (r *Schema) Directives() []Directive { - var names []string - for name := range r.schema.Directives { - names = append(names, name) - } - sort.Strings(names) - - l := make([]Directive, len(names)) - for i, name := range names { - l[i] = Directive{r.schema.Directives[name]} - } - return l -} - -func (r *Schema) QueryType() Type { - t, ok := r.schema.EntryPoints["query"] - if !ok { - return Type{} - } - return Type{t} -} - -func (r *Schema) MutationType() *Type { - t, ok := r.schema.EntryPoints["mutation"] - if !ok { - return nil - } - return &Type{t} -} - -func (r *Schema) SubscriptionType() *Type { - t, ok := r.schema.EntryPoints["subscription"] - if !ok { - return nil - } - return &Type{t} -} - -type Type struct { - typ common.Type -} - -// WrapType is only used internally. -func WrapType(typ common.Type) *Type { - return &Type{typ} -} - -func (r *Type) Kind() string { - return r.typ.Kind() -} - -func (r *Type) Name() *string { - if named, ok := r.typ.(schema.NamedType); ok { - name := named.TypeName() - return &name - } - return nil -} - -func (r *Type) Description() *string { - if named, ok := r.typ.(schema.NamedType); ok { - desc := named.Description() - if desc == "" { - return nil - } - return &desc - } - return nil -} - -func (r *Type) Fields(includeDeprecated bool) []Field { - var fields schema.FieldList - switch t := r.typ.(type) { - case *schema.Object: - fields = t.Fields - case *schema.Interface: - fields = t.Fields - default: - return nil - } - - var l []Field - for _, f := range fields { - if d := f.Directives.Get("deprecated"); d == nil || includeDeprecated { - l = append(l, Field{f}) - } - } - return l -} - -func (r *Type) Interfaces() []Type { - t, ok := r.typ.(*schema.Object) - if !ok { - return nil - } - - l := make([]Type, len(t.Interfaces)) - for i, intf := range t.Interfaces { - l[i] = Type{intf} - } - return l -} - -func (r *Type) PossibleTypes() []Type { - var possibleTypes []*schema.Object - switch t := r.typ.(type) { - case *schema.Interface: - possibleTypes = t.PossibleTypes - case *schema.Union: - possibleTypes = t.PossibleTypes - default: - return nil - } - - l := make([]Type, len(possibleTypes)) - for i, intf := range possibleTypes { - l[i] = Type{intf} - } - return l -} - -func (r *Type) EnumValues(includeDeprecated bool) []EnumValue { - t, ok := r.typ.(*schema.Enum) - if !ok { - return nil - } - - var l []EnumValue - for _, v := range t.Values { - if d := v.Directives.Get("deprecated"); d == nil || includeDeprecated { - l = append(l, EnumValue{v}) - } - } - return l -} - -func (r *Type) InputFields() []InputValue { - t, ok := r.typ.(*schema.InputObject) - if !ok { - return nil - } - - l := make([]InputValue, len(t.Values)) - for i, v := range t.Values { - l[i] = InputValue{v} - } - return l -} - -func (r *Type) OfType() *Type { - switch t := r.typ.(type) { - case *common.List: - return &Type{t.OfType} - case *common.NonNull: - return &Type{t.OfType} - default: - return nil - } -} - -type Field struct { - field *schema.Field -} - -func (r *Field) Name() string { - return r.field.Name -} - -func (r *Field) Description() *string { - if r.field.Desc == "" { - return nil - } - return &r.field.Desc -} - -func (r *Field) Args() []InputValue { - l := make([]InputValue, len(r.field.Args)) - for i, v := range r.field.Args { - l[i] = InputValue{v} - } - return l -} - -func (r *Field) Type() Type { - return Type{r.field.Type} -} - -func (r *Field) IsDeprecated() bool { - return r.field.Directives.Get("deprecated") != nil -} - -func (r *Field) DeprecationReason() *string { - d := r.field.Directives.Get("deprecated") - if d == nil { - return nil - } - reason := d.Args.MustGet("reason").Value(nil).(string) - return &reason -} - -type InputValue struct { - value *common.InputValue -} - -func (r *InputValue) Name() string { - return r.value.Name.Name -} - -func (r *InputValue) Description() *string { - if r.value.Desc == "" { - return nil - } - return &r.value.Desc -} - -func (r *InputValue) Type() Type { - return Type{r.value.Type} -} - -func (r *InputValue) DefaultValue() *string { - if r.value.Default == nil { - return nil - } - s := r.value.Default.String() - return &s -} - -type EnumValue struct { - value *schema.EnumValue -} - -func (r *EnumValue) Name() string { - return r.value.Name -} - -func (r *EnumValue) Description() *string { - if r.value.Desc == "" { - return nil - } - return &r.value.Desc -} - -func (r *EnumValue) IsDeprecated() bool { - return r.value.Directives.Get("deprecated") != nil -} - -func (r *EnumValue) DeprecationReason() *string { - d := r.value.Directives.Get("deprecated") - if d == nil { - return nil - } - reason := d.Args.MustGet("reason").Value(nil).(string) - return &reason -} - -type Directive struct { - directive *schema.DirectiveDecl -} - -func (r *Directive) Name() string { - return r.directive.Name -} - -func (r *Directive) Description() *string { - if r.directive.Desc == "" { - return nil - } - return &r.directive.Desc -} - -func (r *Directive) Locations() []string { - return r.directive.Locs -} - -func (r *Directive) Args() []InputValue { - l := make([]InputValue, len(r.directive.Args)) - for i, v := range r.directive.Args { - l[i] = InputValue{v} - } - return l -} diff --git a/neelance/query/query.go b/neelance/query/query.go deleted file mode 100644 index b6f35354f30..00000000000 --- a/neelance/query/query.go +++ /dev/null @@ -1,261 +0,0 @@ -package query - -import ( - "fmt" - "strings" - "text/scanner" - - "github.com/vektah/gqlgen/neelance/common" - "github.com/vektah/gqlgen/neelance/errors" -) - -type Document struct { - Operations OperationList - Fragments FragmentList -} - -type OperationList []*Operation - -func (l OperationList) Get(name string) *Operation { - for _, f := range l { - if f.Name.Name == name { - return f - } - } - return nil -} - -type FragmentList []*FragmentDecl - -func (l FragmentList) Get(name string) *FragmentDecl { - for _, f := range l { - if f.Name.Name == name { - return f - } - } - return nil -} - -type Operation struct { - Type OperationType - Name common.Ident - Vars common.InputValueList - Selections []Selection - Directives common.DirectiveList - Loc errors.Location -} - -type OperationType string - -const ( - Query OperationType = "QUERY" - Mutation = "MUTATION" - Subscription = "SUBSCRIPTION" -) - -type Fragment struct { - On common.TypeName - Selections []Selection -} - -type FragmentDecl struct { - Fragment - Name common.Ident - Directives common.DirectiveList - Loc errors.Location -} - -type Selection interface { - isSelection() -} - -type Field struct { - Alias common.Ident - Name common.Ident - Arguments common.ArgumentList - Directives common.DirectiveList - Selections []Selection - SelectionSetLoc errors.Location -} - -type InlineFragment struct { - Fragment - Directives common.DirectiveList - Loc errors.Location -} - -type FragmentSpread struct { - Name common.Ident - Directives common.DirectiveList - Loc errors.Location -} - -func (Field) isSelection() {} -func (InlineFragment) isSelection() {} -func (FragmentSpread) isSelection() {} - -func Parse(queryString string) (*Document, *errors.QueryError) { - sc := &scanner.Scanner{ - Mode: scanner.ScanIdents | scanner.ScanInts | scanner.ScanFloats | scanner.ScanStrings, - } - sc.Init(strings.NewReader(queryString)) - - l := common.New(sc) - var doc *Document - err := l.CatchSyntaxError(func() { - doc = parseDocument(l) - }) - if err != nil { - return nil, err - } - - return doc, nil -} - -func parseDocument(l *common.Lexer) *Document { - d := &Document{} - for l.Peek() != scanner.EOF { - if l.Peek() == '{' { - op := &Operation{Type: Query, Loc: l.Location()} - op.Selections = parseSelectionSet(l) - d.Operations = append(d.Operations, op) - continue - } - - loc := l.Location() - switch x := l.ConsumeIdent(); x { - case "query": - op := parseOperation(l, Query) - op.Loc = loc - d.Operations = append(d.Operations, op) - - case "mutation": - d.Operations = append(d.Operations, parseOperation(l, Mutation)) - - case "subscription": - d.Operations = append(d.Operations, parseOperation(l, Subscription)) - - case "fragment": - frag := parseFragment(l) - frag.Loc = loc - d.Fragments = append(d.Fragments, frag) - - default: - l.SyntaxError(fmt.Sprintf(`unexpected %q, expecting "fragment"`, x)) - } - } - return d -} - -func parseOperation(l *common.Lexer, opType OperationType) *Operation { - op := &Operation{Type: opType} - op.Name.Loc = l.Location() - if l.Peek() == scanner.Ident { - op.Name = l.ConsumeIdentWithLoc() - } - op.Directives = common.ParseDirectives(l) - if l.Peek() == '(' { - l.ConsumeToken('(') - for l.Peek() != ')' { - loc := l.Location() - l.ConsumeToken('$') - iv := common.ParseInputValue(l) - iv.Loc = loc - op.Vars = append(op.Vars, iv) - } - l.ConsumeToken(')') - } - op.Selections = parseSelectionSet(l) - return op -} - -func parseFragment(l *common.Lexer) *FragmentDecl { - f := &FragmentDecl{} - f.Name = l.ConsumeIdentWithLoc() - l.ConsumeKeyword("on") - f.On = common.TypeName{Ident: l.ConsumeIdentWithLoc()} - f.Directives = common.ParseDirectives(l) - f.Selections = parseSelectionSet(l) - return f -} - -func parseSelectionSet(l *common.Lexer) []Selection { - var sels []Selection - l.ConsumeToken('{') - for l.Peek() != '}' { - sels = append(sels, parseSelection(l)) - } - l.ConsumeToken('}') - return sels -} - -func parseSelection(l *common.Lexer) Selection { - if l.Peek() == '.' { - return parseSpread(l) - } - return parseField(l) -} - -func parseField(l *common.Lexer) *Field { - f := &Field{} - f.Alias = l.ConsumeIdentWithLoc() - f.Name = f.Alias - if l.Peek() == ':' { - l.ConsumeToken(':') - f.Name = l.ConsumeIdentWithLoc() - } - if l.Peek() == '(' { - f.Arguments = common.ParseArguments(l) - } - f.Directives = common.ParseDirectives(l) - if l.Peek() == '{' { - f.SelectionSetLoc = l.Location() - f.Selections = parseSelectionSet(l) - } - return f -} - -func parseSpread(l *common.Lexer) Selection { - loc := l.Location() - l.ConsumeToken('.') - l.ConsumeToken('.') - l.ConsumeToken('.') - - f := &InlineFragment{Loc: loc} - if l.Peek() == scanner.Ident { - ident := l.ConsumeIdentWithLoc() - if ident.Name != "on" { - fs := &FragmentSpread{ - Name: ident, - Loc: loc, - } - fs.Directives = common.ParseDirectives(l) - return fs - } - f.On = common.TypeName{Ident: l.ConsumeIdentWithLoc()} - } - f.Directives = common.ParseDirectives(l) - f.Selections = parseSelectionSet(l) - return f -} - -func (d *Document) GetOperation(operationName string) (*Operation, error) { - if len(d.Operations) == 0 { - return nil, fmt.Errorf("no operations in query document") - } - - if operationName == "" { - if len(d.Operations) > 1 { - return nil, fmt.Errorf("more than one operation in query document and no operation name given") - } - for _, op := range d.Operations { - return op, nil // return the one and only operation - } - } - - op := d.Operations.Get(operationName) - if op == nil { - return nil, fmt.Errorf("no operation with name %q", operationName) - } - return op, nil -} diff --git a/neelance/readme.md b/neelance/readme.md deleted file mode 100644 index 1ecb2ce965b..00000000000 --- a/neelance/readme.md +++ /dev/null @@ -1,6 +0,0 @@ -### neelance - -This code has been copied from https://github.com/neelance/graphql-go. - -I hope that https://github.com/neelance/graphql-go/issues/116 gets fixed and these packages can be referenced -directly from his repo, instead of being copied here diff --git a/neelance/schema/meta.go b/neelance/schema/meta.go deleted file mode 100644 index efdcaa2c493..00000000000 --- a/neelance/schema/meta.go +++ /dev/null @@ -1,193 +0,0 @@ -package schema - -var Meta *Schema - -func init() { - Meta = &Schema{} // bootstrap - Meta = New() - if err := Meta.Parse(metaSrc); err != nil { - panic(err) - } -} - -var metaSrc = ` - # The ` + "`" + `Int` + "`" + ` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. - scalar Int - - # The ` + "`" + `Float` + "`" + ` scalar type represents signed double-precision fractional values as specified by [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point). - scalar Float - - # The ` + "`" + `String` + "`" + ` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. - scalar String - - # The ` + "`" + `Boolean` + "`" + ` scalar type represents ` + "`" + `true` + "`" + ` or ` + "`" + `false` + "`" + `. - scalar Boolean - - # The ` + "`" + `ID` + "`" + ` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as ` + "`" + `"4"` + "`" + `) or integer (such as ` + "`" + `4` + "`" + `) input value will be accepted as an ID. - scalar ID - - # The ` + "`" + `Map` + "`" + ` scalar type is a simple json object - scalar Map - - # Directs the executor to include this field or fragment only when the ` + "`" + `if` + "`" + ` argument is true. - directive @include( - # Included when true. - if: Boolean! - ) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT - - # Directs the executor to skip this field or fragment when the ` + "`" + `if` + "`" + ` argument is true. - directive @skip( - # Skipped when true. - if: Boolean! - ) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT - - # Marks an element of a GraphQL schema as no longer supported. - directive @deprecated( - # Explains why this element was deprecated, usually also including a suggestion - # for how to access supported similar data. Formatted in - # [Markdown](https://daringfireball.net/projects/markdown/). - reason: String = "No longer supported" - ) on FIELD_DEFINITION | ENUM_VALUE - - # A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document. - # - # In some cases, you need to provide options to alter GraphQL's execution behavior - # in ways field arguments will not suffice, such as conditionally including or - # skipping a field. Directives provide this by describing additional information - # to the executor. - type __Directive { - name: String! - description: String - locations: [__DirectiveLocation!]! - args: [__InputValue!]! - } - - # A Directive can be adjacent to many parts of the GraphQL language, a - # __DirectiveLocation describes one such possible adjacencies. - enum __DirectiveLocation { - # Location adjacent to a query operation. - QUERY - # Location adjacent to a mutation operation. - MUTATION - # Location adjacent to a subscription operation. - SUBSCRIPTION - # Location adjacent to a field. - FIELD - # Location adjacent to a fragment definition. - FRAGMENT_DEFINITION - # Location adjacent to a fragment spread. - FRAGMENT_SPREAD - # Location adjacent to an inline fragment. - INLINE_FRAGMENT - # Location adjacent to a schema definition. - SCHEMA - # Location adjacent to a scalar definition. - SCALAR - # Location adjacent to an object type definition. - OBJECT - # Location adjacent to a field definition. - FIELD_DEFINITION - # Location adjacent to an argument definition. - ARGUMENT_DEFINITION - # Location adjacent to an interface definition. - INTERFACE - # Location adjacent to a union definition. - UNION - # Location adjacent to an enum definition. - ENUM - # Location adjacent to an enum value definition. - ENUM_VALUE - # Location adjacent to an input object type definition. - INPUT_OBJECT - # Location adjacent to an input object field definition. - INPUT_FIELD_DEFINITION - } - - # One possible value for a given Enum. Enum values are unique values, not a - # placeholder for a string or numeric value. However an Enum value is returned in - # a JSON response as a string. - type __EnumValue { - name: String! - description: String - isDeprecated: Boolean! - deprecationReason: String - } - - # Object and Interface types are described by a list of Fields, each of which has - # a name, potentially a list of arguments, and a return type. - type __Field { - name: String! - description: String - args: [__InputValue!]! - type: __Type! - isDeprecated: Boolean! - deprecationReason: String - } - - # Arguments provided to Fields or Directives and the input fields of an - # InputObject are represented as Input Values which describe their type and - # optionally a default value. - type __InputValue { - name: String! - description: String - type: __Type! - # A GraphQL-formatted string representing the default value for this input value. - defaultValue: String - } - - # A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all - # available types and directives on the server, as well as the entry points for - # query, mutation, and subscription operations. - type __Schema { - # A list of all types supported by this server. - types: [__Type!]! - # The type that query operations will be rooted at. - queryType: __Type! - # If this server supports mutation, the type that mutation operations will be rooted at. - mutationType: __Type - # If this server support subscription, the type that subscription operations will be rooted at. - subscriptionType: __Type - # A list of all directives supported by this server. - directives: [__Directive!]! - } - - # The fundamental unit of any GraphQL Schema is the type. There are many kinds of - # types in GraphQL as represented by the ` + "`" + `__TypeKind` + "`" + ` enum. - # - # Depending on the kind of a type, certain fields describe information about that - # type. Scalar types provide no information beyond a name and description, while - # Enum types provide their values. Object and Interface types provide the fields - # they describe. Abstract types, Union and Interface, provide the Object types - # possible at runtime. List and NonNull types compose other types. - type __Type { - kind: __TypeKind! - name: String - description: String - fields(includeDeprecated: Boolean = false): [__Field!] - interfaces: [__Type!] - possibleTypes: [__Type!] - enumValues(includeDeprecated: Boolean = false): [__EnumValue!] - inputFields: [__InputValue!] - ofType: __Type - } - - # An enum describing what kind of type a given ` + "`" + `__Type` + "`" + ` is. - enum __TypeKind { - # Indicates this type is a scalar. - SCALAR - # Indicates this type is an object. ` + "`" + `fields` + "`" + ` and ` + "`" + `interfaces` + "`" + ` are valid fields. - OBJECT - # Indicates this type is an interface. ` + "`" + `fields` + "`" + ` and ` + "`" + `possibleTypes` + "`" + ` are valid fields. - INTERFACE - # Indicates this type is a union. ` + "`" + `possibleTypes` + "`" + ` is a valid field. - UNION - # Indicates this type is an enum. ` + "`" + `enumValues` + "`" + ` is a valid field. - ENUM - # Indicates this type is an input object. ` + "`" + `inputFields` + "`" + ` is a valid field. - INPUT_OBJECT - # Indicates this type is a list. ` + "`" + `ofType` + "`" + ` is a valid field. - LIST - # Indicates this type is a non-null. ` + "`" + `ofType` + "`" + ` is a valid field. - NON_NULL - } -` diff --git a/neelance/schema/schema.go b/neelance/schema/schema.go deleted file mode 100644 index 0b1317a5e4b..00000000000 --- a/neelance/schema/schema.go +++ /dev/null @@ -1,489 +0,0 @@ -package schema - -import ( - "fmt" - "strings" - "text/scanner" - - "github.com/vektah/gqlgen/neelance/common" - "github.com/vektah/gqlgen/neelance/errors" -) - -type Schema struct { - EntryPoints map[string]NamedType - Types map[string]NamedType - Directives map[string]*DirectiveDecl - - entryPointNames map[string]string - objects []*Object - unions []*Union - enums []*Enum -} - -var defaultEntrypoints = map[string]string{ - "query": "Query", - "mutation": "Mutation", - "subscription": "Subscription", -} - -func (s *Schema) Resolve(name string) common.Type { - return s.Types[name] -} - -type NamedType interface { - common.Type - TypeName() string - Description() string -} - -type Scalar struct { - Name string - Desc string -} - -type Object struct { - Name string - Interfaces []*Interface - Fields FieldList - Desc string - - interfaceNames []string -} - -type Interface struct { - Name string - PossibleTypes []*Object - Fields FieldList - Desc string -} - -type Union struct { - Name string - PossibleTypes []*Object - Desc string - - typeNames []string -} - -type Enum struct { - Name string - Values []*EnumValue - Desc string -} - -type EnumValue struct { - Name string - Directives common.DirectiveList - Desc string -} - -type InputObject struct { - Name string - Desc string - Values common.InputValueList -} - -type FieldList []*Field - -func (l FieldList) Get(name string) *Field { - for _, f := range l { - if f.Name == name { - return f - } - } - return nil -} - -func (l FieldList) Names() []string { - names := make([]string, len(l)) - for i, f := range l { - names[i] = f.Name - } - return names -} - -type DirectiveDecl struct { - Name string - Desc string - Locs []string - Args common.InputValueList -} - -func (*Scalar) Kind() string { return "SCALAR" } -func (*Object) Kind() string { return "OBJECT" } -func (*Interface) Kind() string { return "INTERFACE" } -func (*Union) Kind() string { return "UNION" } -func (*Enum) Kind() string { return "ENUM" } -func (*InputObject) Kind() string { return "INPUT_OBJECT" } - -func (t *Scalar) String() string { return t.Name } -func (t *Object) String() string { return t.Name } -func (t *Interface) String() string { return t.Name } -func (t *Union) String() string { return t.Name } -func (t *Enum) String() string { return t.Name } -func (t *InputObject) String() string { return t.Name } - -func (t *Scalar) TypeName() string { return t.Name } -func (t *Object) TypeName() string { return t.Name } -func (t *Interface) TypeName() string { return t.Name } -func (t *Union) TypeName() string { return t.Name } -func (t *Enum) TypeName() string { return t.Name } -func (t *InputObject) TypeName() string { return t.Name } - -func (t *Scalar) Description() string { return t.Desc } -func (t *Object) Description() string { return t.Desc } -func (t *Interface) Description() string { return t.Desc } -func (t *Union) Description() string { return t.Desc } -func (t *Enum) Description() string { return t.Desc } -func (t *InputObject) Description() string { return t.Desc } - -type Field struct { - Name string - Args common.InputValueList - Type common.Type - Directives common.DirectiveList - Desc string -} - -func MustParse(str string) *Schema { - s := New() - err := s.Parse(str) - if err != nil { - panic(err) - } - return s -} - -func New() *Schema { - s := &Schema{ - entryPointNames: make(map[string]string), - Types: make(map[string]NamedType), - Directives: make(map[string]*DirectiveDecl), - } - for n, t := range Meta.Types { - s.Types[n] = t - } - for n, d := range Meta.Directives { - s.Directives[n] = d - } - return s -} - -func (s *Schema) Parse(schemaString string) error { - sc := &scanner.Scanner{ - Mode: scanner.ScanIdents | scanner.ScanInts | scanner.ScanFloats | scanner.ScanStrings, - } - sc.Init(strings.NewReader(schemaString)) - - l := common.New(sc) - err := l.CatchSyntaxError(func() { - parseSchema(s, l) - }) - if err != nil { - return err - } - - for _, t := range s.Types { - if err := resolveNamedType(s, t); err != nil { - return err - } - } - for _, d := range s.Directives { - for _, arg := range d.Args { - t, err := common.ResolveType(arg.Type, s.Resolve) - if err != nil { - return err - } - arg.Type = t - } - } - - s.EntryPoints = make(map[string]NamedType) - for key, name := range s.entryPointNames { - t, ok := s.Types[name] - if !ok { - if !ok { - return errors.Errorf("type %q not found", name) - } - } - s.EntryPoints[key] = t - } - - for entrypointName, typeName := range defaultEntrypoints { - if _, ok := s.EntryPoints[entrypointName]; ok { - continue - } - - if _, ok := s.Types[typeName]; !ok { - continue - } - - s.EntryPoints[entrypointName] = s.Types[typeName] - } - - for _, obj := range s.objects { - obj.Interfaces = make([]*Interface, len(obj.interfaceNames)) - for i, intfName := range obj.interfaceNames { - t, ok := s.Types[intfName] - if !ok { - return errors.Errorf("interface %q not found", intfName) - } - intf, ok := t.(*Interface) - if !ok { - return errors.Errorf("type %q is not an interface", intfName) - } - obj.Interfaces[i] = intf - intf.PossibleTypes = append(intf.PossibleTypes, obj) - } - } - - for _, union := range s.unions { - union.PossibleTypes = make([]*Object, len(union.typeNames)) - for i, name := range union.typeNames { - t, ok := s.Types[name] - if !ok { - return errors.Errorf("object type %q not found", name) - } - obj, ok := t.(*Object) - if !ok { - return errors.Errorf("type %q is not an object", name) - } - union.PossibleTypes[i] = obj - } - } - - for _, enum := range s.enums { - for _, value := range enum.Values { - if err := resolveDirectives(s, value.Directives); err != nil { - return err - } - } - } - - return nil -} - -func resolveNamedType(s *Schema, t NamedType) error { - switch t := t.(type) { - case *Object: - for _, f := range t.Fields { - if err := resolveField(s, f); err != nil { - return err - } - } - case *Interface: - for _, f := range t.Fields { - if err := resolveField(s, f); err != nil { - return err - } - } - case *InputObject: - if err := resolveInputObject(s, t.Values); err != nil { - return err - } - } - return nil -} - -func resolveField(s *Schema, f *Field) error { - t, err := common.ResolveType(f.Type, s.Resolve) - if err != nil { - return err - } - f.Type = t - if err := resolveDirectives(s, f.Directives); err != nil { - return err - } - return resolveInputObject(s, f.Args) -} - -func resolveDirectives(s *Schema, directives common.DirectiveList) error { - for _, d := range directives { - dirName := d.Name.Name - dd, ok := s.Directives[dirName] - if !ok { - return errors.Errorf("directive %q not found", dirName) - } - for _, arg := range d.Args { - if dd.Args.Get(arg.Name.Name) == nil { - return errors.Errorf("invalid argument %q for directive %q", arg.Name.Name, dirName) - } - } - for _, arg := range dd.Args { - if _, ok := d.Args.Get(arg.Name.Name); !ok { - d.Args = append(d.Args, common.Argument{Name: arg.Name, Value: arg.Default}) - } - } - } - return nil -} - -func resolveInputObject(s *Schema, values common.InputValueList) error { - for _, v := range values { - t, err := common.ResolveType(v.Type, s.Resolve) - if err != nil { - return err - } - v.Type = t - } - return nil -} - -func parseSchema(s *Schema, l *common.Lexer) { - for l.Peek() != scanner.EOF { - desc := l.DescComment() - switch x := l.ConsumeIdent(); x { - case "schema": - l.ConsumeToken('{') - for l.Peek() != '}' { - name := l.ConsumeIdent() - l.ConsumeToken(':') - typ := l.ConsumeIdent() - s.entryPointNames[name] = typ - } - l.ConsumeToken('}') - case "type": - obj := parseObjectDecl(l) - obj.Desc = desc - s.Types[obj.Name] = obj - s.objects = append(s.objects, obj) - case "interface": - intf := parseInterfaceDecl(l) - intf.Desc = desc - s.Types[intf.Name] = intf - case "union": - union := parseUnionDecl(l) - union.Desc = desc - s.Types[union.Name] = union - s.unions = append(s.unions, union) - case "enum": - enum := parseEnumDecl(l) - enum.Desc = desc - s.Types[enum.Name] = enum - s.enums = append(s.enums, enum) - case "input": - input := parseInputDecl(l) - input.Desc = desc - s.Types[input.Name] = input - case "scalar": - name := l.ConsumeIdent() - s.Types[name] = &Scalar{Name: name, Desc: desc} - case "directive": - directive := parseDirectiveDecl(l) - directive.Desc = desc - s.Directives[directive.Name] = directive - default: - l.SyntaxError(fmt.Sprintf(`unexpected %q, expecting "schema", "type", "enum", "interface", "union", "input", "scalar" or "directive"`, x)) - } - } -} - -func parseObjectDecl(l *common.Lexer) *Object { - o := &Object{} - o.Name = l.ConsumeIdent() - if l.Peek() == scanner.Ident { - l.ConsumeKeyword("implements") - for { - o.interfaceNames = append(o.interfaceNames, l.ConsumeIdent()) - if l.Peek() == '{' { - break - } - } - } - l.ConsumeToken('{') - o.Fields = parseFields(l) - l.ConsumeToken('}') - return o -} - -func parseInterfaceDecl(l *common.Lexer) *Interface { - i := &Interface{} - i.Name = l.ConsumeIdent() - l.ConsumeToken('{') - i.Fields = parseFields(l) - l.ConsumeToken('}') - return i -} - -func parseUnionDecl(l *common.Lexer) *Union { - union := &Union{} - union.Name = l.ConsumeIdent() - l.ConsumeToken('=') - union.typeNames = []string{l.ConsumeIdent()} - for l.Peek() == '|' { - l.ConsumeToken('|') - union.typeNames = append(union.typeNames, l.ConsumeIdent()) - } - return union -} - -func parseInputDecl(l *common.Lexer) *InputObject { - i := &InputObject{} - i.Name = l.ConsumeIdent() - l.ConsumeToken('{') - for l.Peek() != '}' { - i.Values = append(i.Values, common.ParseInputValue(l)) - } - l.ConsumeToken('}') - return i -} - -func parseEnumDecl(l *common.Lexer) *Enum { - enum := &Enum{} - enum.Name = l.ConsumeIdent() - l.ConsumeToken('{') - for l.Peek() != '}' { - v := &EnumValue{} - v.Desc = l.DescComment() - v.Name = l.ConsumeIdent() - v.Directives = common.ParseDirectives(l) - enum.Values = append(enum.Values, v) - } - l.ConsumeToken('}') - return enum -} - -func parseDirectiveDecl(l *common.Lexer) *DirectiveDecl { - d := &DirectiveDecl{} - l.ConsumeToken('@') - d.Name = l.ConsumeIdent() - if l.Peek() == '(' { - l.ConsumeToken('(') - for l.Peek() != ')' { - v := common.ParseInputValue(l) - d.Args = append(d.Args, v) - } - l.ConsumeToken(')') - } - l.ConsumeKeyword("on") - for { - loc := l.ConsumeIdent() - d.Locs = append(d.Locs, loc) - if l.Peek() != '|' { - break - } - l.ConsumeToken('|') - } - return d -} - -func parseFields(l *common.Lexer) FieldList { - var fields FieldList - for l.Peek() != '}' { - f := &Field{} - f.Desc = l.DescComment() - f.Name = l.ConsumeIdent() - if l.Peek() == '(' { - l.ConsumeToken('(') - for l.Peek() != ')' { - f.Args = append(f.Args, common.ParseInputValue(l)) - } - l.ConsumeToken(')') - } - l.ConsumeToken(':') - f.Type = common.ParseType(l) - f.Directives = common.ParseDirectives(l) - fields = append(fields, f) - } - return fields -} diff --git a/neelance/tests/all_test.go b/neelance/tests/all_test.go deleted file mode 100644 index b58d2009594..00000000000 --- a/neelance/tests/all_test.go +++ /dev/null @@ -1,75 +0,0 @@ -package tests - -import ( - "os" - "reflect" - "sort" - "testing" - - "encoding/json" - - "github.com/vektah/gqlgen/neelance/errors" - "github.com/vektah/gqlgen/neelance/query" - "github.com/vektah/gqlgen/neelance/schema" - "github.com/vektah/gqlgen/neelance/validation" -) - -type Test struct { - Name string - Rule string - Schema int - Query string - Errors []*errors.QueryError -} - -func TestAll(t *testing.T) { - f, err := os.Open("testdata/tests.json") - if err != nil { - t.Fatal(err) - } - - var testData struct { - Schemas []string - Tests []*Test - } - if err := json.NewDecoder(f).Decode(&testData); err != nil { - t.Fatal(err) - } - - schemas := make([]*schema.Schema, len(testData.Schemas)) - for i, schemaStr := range testData.Schemas { - schemas[i] = schema.New() - if err := schemas[i].Parse(schemaStr); err != nil { - t.Fatal(err) - } - } - - for _, test := range testData.Tests { - t.Run(test.Name, func(t *testing.T) { - d, err := query.Parse(test.Query) - if err != nil { - t.Fatal(err) - } - errs := validation.Validate(schemas[test.Schema], d) - got := []*errors.QueryError{} - for _, err := range errs { - if err.Rule == test.Rule { - err.Rule = "" - got = append(got, err) - } - } - sortLocations(test.Errors) - sortLocations(got) - if !reflect.DeepEqual(test.Errors, got) { - t.Errorf("wrong errors\nexpected: %v\ngot: %v", test.Errors, got) - } - }) - } -} - -func sortLocations(errs []*errors.QueryError) { - for _, err := range errs { - locs := err.Locations - sort.Slice(locs, func(i, j int) bool { return locs[i].Before(locs[j]) }) - } -} diff --git a/neelance/tests/empty.go b/neelance/tests/empty.go deleted file mode 100644 index ca8701d290d..00000000000 --- a/neelance/tests/empty.go +++ /dev/null @@ -1 +0,0 @@ -package tests diff --git a/neelance/tests/testdata/LICENSE b/neelance/tests/testdata/LICENSE deleted file mode 100644 index fce4519eb40..00000000000 --- a/neelance/tests/testdata/LICENSE +++ /dev/null @@ -1,33 +0,0 @@ -The files in this testdata directory are derived from the graphql-js project: -https://github.com/graphql/graphql-js - -BSD License - -For GraphQL software - -Copyright (c) 2015, Facebook, Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - * Neither the name Facebook nor the names of its contributors may be used to - endorse or promote products derived from this software without specific - prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/neelance/tests/testdata/export.js b/neelance/tests/testdata/export.js deleted file mode 100644 index b89f5574396..00000000000 --- a/neelance/tests/testdata/export.js +++ /dev/null @@ -1,110 +0,0 @@ -import fs from 'fs'; -import Module from 'module'; -import { testSchema } from './src/validation/__tests__/harness'; -import { printSchema } from './src/utilities'; - -let schemas = []; -function registerSchema(schema) { - for (let i = 0; i < schemas.length; i++) { - if (schemas[i] == schema) { - return i; - } - } - schemas.push(schema); - return schemas.length - 1; -} - -const harness = { - expectPassesRule(rule, queryString) { - harness.expectPassesRuleWithSchema(testSchema, rule, queryString); - }, - expectPassesRuleWithSchema(schema, rule, queryString, errors) { - tests.push({ - name: names.join('/'), - rule: rule.name, - schema: registerSchema(schema), - query: queryString, - errors: [], - }); - }, - expectFailsRule(rule, queryString, errors) { - harness.expectFailsRuleWithSchema(testSchema, rule, queryString, errors); - }, - expectFailsRuleWithSchema(schema, rule, queryString, errors) { - tests.push({ - name: names.join('/'), - rule: rule.name, - schema: registerSchema(schema), - query: queryString, - errors: errors, - }); - } -}; - -let tests = []; -let names = [] -const fakeModules = { - 'mocha': { - describe(name, f) { - switch (name) { - case 'within schema language': - return; - } - names.push(name); - f(); - names.pop(); - }, - it(name, f) { - switch (name) { - case 'ignores type definitions': - case 'reports correctly when a non-exclusive follows an exclusive': - case 'disallows differing subfields': - return; - } - names.push(name); - f(); - names.pop(); - }, - }, - './harness': harness, -}; - -const originalLoader = Module._load; -Module._load = function(request, parent, isMain) { - return fakeModules[request] || originalLoader(request, parent, isMain); -}; - -require('./src/validation/__tests__/ArgumentsOfCorrectType-test'); -require('./src/validation/__tests__/DefaultValuesOfCorrectType-test'); -require('./src/validation/__tests__/FieldsOnCorrectType-test'); -require('./src/validation/__tests__/FragmentsOnCompositeTypes-test'); -require('./src/validation/__tests__/KnownArgumentNames-test'); -require('./src/validation/__tests__/KnownDirectives-test'); -require('./src/validation/__tests__/KnownFragmentNames-test'); -require('./src/validation/__tests__/KnownTypeNames-test'); -require('./src/validation/__tests__/LoneAnonymousOperation-test'); -require('./src/validation/__tests__/NoFragmentCycles-test'); -require('./src/validation/__tests__/NoUndefinedVariables-test'); -require('./src/validation/__tests__/NoUnusedFragments-test'); -require('./src/validation/__tests__/NoUnusedVariables-test'); -require('./src/validation/__tests__/OverlappingFieldsCanBeMerged-test'); -require('./src/validation/__tests__/PossibleFragmentSpreads-test'); -require('./src/validation/__tests__/ProvidedNonNullArguments-test'); -require('./src/validation/__tests__/ScalarLeafs-test'); -require('./src/validation/__tests__/UniqueArgumentNames-test'); -require('./src/validation/__tests__/UniqueDirectivesPerLocation-test'); -require('./src/validation/__tests__/UniqueFragmentNames-test'); -require('./src/validation/__tests__/UniqueInputFieldNames-test'); -require('./src/validation/__tests__/UniqueOperationNames-test'); -require('./src/validation/__tests__/UniqueVariableNames-test'); -require('./src/validation/__tests__/VariablesAreInputTypes-test'); -require('./src/validation/__tests__/VariablesInAllowedPosition-test'); - -let output = JSON.stringify({ - schemas: schemas.map(s => printSchema(s)), - tests: tests, -}, null, 2) -output = output.replace(' Did you mean to use an inline fragment on \\"Dog\\" or \\"Cat\\"?', ''); -output = output.replace(' Did you mean to use an inline fragment on \\"Being\\", \\"Pet\\", \\"Canine\\", \\"Dog\\", or \\"Cat\\"?', ''); -output = output.replace(' Did you mean \\"Pet\\"?', ''); -fs.writeFileSync("tests.json", output); diff --git a/neelance/tests/testdata/gen.go b/neelance/tests/testdata/gen.go deleted file mode 100644 index 6d5ac9e6bd4..00000000000 --- a/neelance/tests/testdata/gen.go +++ /dev/null @@ -1,4 +0,0 @@ -package testdata - -//go:generate cp export.js graphql-js/export.js -//go:generate babel-node graphql-js/export.js diff --git a/neelance/tests/testdata/tests.json b/neelance/tests/testdata/tests.json deleted file mode 100644 index 35511c6af93..00000000000 --- a/neelance/tests/testdata/tests.json +++ /dev/null @@ -1,4948 +0,0 @@ -{ - "schemas": [ - "schema {\n query: QueryRoot\n}\n\ndirective @onQuery on QUERY\n\ndirective @onMutation on MUTATION\n\ndirective @onSubscription on SUBSCRIPTION\n\ndirective @onField on FIELD\n\ndirective @onFragmentDefinition on FRAGMENT_DEFINITION\n\ndirective @onFragmentSpread on FRAGMENT_SPREAD\n\ndirective @onInlineFragment on INLINE_FRAGMENT\n\ndirective @onSchema on SCHEMA\n\ndirective @onScalar on SCALAR\n\ndirective @onObject on OBJECT\n\ndirective @onFieldDefinition on FIELD_DEFINITION\n\ndirective @onArgumentDefinition on ARGUMENT_DEFINITION\n\ndirective @onInterface on INTERFACE\n\ndirective @onUnion on UNION\n\ndirective @onEnum on ENUM\n\ndirective @onEnumValue on ENUM_VALUE\n\ndirective @onInputObject on INPUT_OBJECT\n\ndirective @onInputFieldDefinition on INPUT_FIELD_DEFINITION\n\ntype Alien implements Being, Intelligent {\n iq: Int\n name(surname: Boolean): String\n numEyes: Int\n}\n\ninterface Being {\n name(surname: Boolean): String\n}\n\ninterface Canine {\n name(surname: Boolean): String\n}\n\ntype Cat implements Being, Pet {\n furColor: FurColor\n meowVolume: Int\n meows: Boolean\n name(surname: Boolean): String\n nickname: String\n}\n\nunion CatOrDog = Dog | Cat\n\ninput ComplexInput {\n booleanField: Boolean\n intField: Int\n requiredField: Boolean!\n stringField: String\n stringListField: [String]\n}\n\ntype ComplicatedArgs {\n booleanArgField(booleanArg: Boolean): String\n complexArgField(complexArg: ComplexInput): String\n enumArgField(enumArg: FurColor): String\n floatArgField(floatArg: Float): String\n idArgField(idArg: ID): String\n intArgField(intArg: Int): String\n multipleOptAndReq(req1: Int!, req2: Int!, opt1: Int = 0, opt2: Int = 0): String\n multipleOpts(opt1: Int = 0, opt2: Int = 0): String\n multipleReqs(req1: Int!, req2: Int!): String\n nonNullIntArgField(nonNullIntArg: Int!): String\n stringArgField(stringArg: String): String\n stringListArgField(stringListArg: [String]): String\n}\n\ntype Dog implements Being, Pet, Canine {\n barkVolume: Int\n barks: Boolean\n doesKnowCommand(dogCommand: DogCommand): Boolean\n isAtLocation(x: Int, y: Int): Boolean\n isHousetrained(atOtherHomes: Boolean = true): Boolean\n name(surname: Boolean): String\n nickname: String\n}\n\nenum DogCommand {\n SIT\n HEEL\n DOWN\n}\n\nunion DogOrHuman = Dog | Human\n\nenum FurColor {\n BROWN\n BLACK\n TAN\n SPOTTED\n NO_FUR\n UNKNOWN\n}\n\ntype Human implements Being, Intelligent {\n iq: Int\n name(surname: Boolean): String\n pets: [Pet]\n relatives: [Human]\n}\n\nunion HumanOrAlien = Human | Alien\n\ninterface Intelligent {\n iq: Int\n}\n\ninterface Pet {\n name(surname: Boolean): String\n}\n\ntype QueryRoot {\n alien: Alien\n cat: Cat\n catOrDog: CatOrDog\n complicatedArgs: ComplicatedArgs\n dog: Dog\n dogOrHuman: DogOrHuman\n human(id: ID): Human\n humanOrAlien: HumanOrAlien\n pet: Pet\n}\n", - "schema {\n query: QueryRoot\n}\n\ntype Connection {\n edges: [Edge]\n}\n\ntype Edge {\n node: Node\n}\n\ntype IntBox implements SomeBox {\n deepBox: IntBox\n intBox: IntBox\n listStringBox: [StringBox]\n scalar: Int\n stringBox: StringBox\n unrelatedField: String\n}\n\ntype Node {\n id: ID\n name: String\n}\n\ninterface NonNullStringBox1 {\n scalar: String!\n}\n\ntype NonNullStringBox1Impl implements SomeBox, NonNullStringBox1 {\n deepBox: SomeBox\n scalar: String!\n unrelatedField: String\n}\n\ninterface NonNullStringBox2 {\n scalar: String!\n}\n\ntype NonNullStringBox2Impl implements SomeBox, NonNullStringBox2 {\n deepBox: SomeBox\n scalar: String!\n unrelatedField: String\n}\n\ntype QueryRoot {\n connection: Connection\n someBox: SomeBox\n}\n\ninterface SomeBox {\n deepBox: SomeBox\n unrelatedField: String\n}\n\ntype StringBox implements SomeBox {\n deepBox: StringBox\n intBox: IntBox\n listStringBox: [StringBox]\n scalar: String\n stringBox: StringBox\n unrelatedField: String\n}\n", - "type Foo {\n constructor: String\n}\n\ntype Query {\n foo: Foo\n}\n" - ], - "tests": [ - { - "name": "Validate: Argument values of correct type/Valid values/Good int value", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n intArgField(intArg: 2)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid values/Good negative int value", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n intArgField(intArg: -2)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid values/Good boolean value", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n booleanArgField(booleanArg: true)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid values/Good string value", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n stringArgField(stringArg: \"foo\")\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid values/Good float value", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n floatArgField(floatArg: 1.1)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid values/Good negative float value", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n floatArgField(floatArg: -1.1)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid values/Int into Float", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n floatArgField(floatArg: 1)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid values/Int into ID", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n idArgField(idArg: 1)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid values/String into ID", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n idArgField(idArg: \"someIdString\")\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid values/Good enum value", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n dog {\n doesKnowCommand(dogCommand: SIT)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid values/Enum with undefined value", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n enumArgField(enumArg: UNKNOWN)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid values/Enum with null value", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n enumArgField(enumArg: NO_FUR)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid values/null into nullable type", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n intArgField(intArg: null)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid values/null into nullable type", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n dog(a: null, b: null, c:{ requiredField: true, intField: null }) {\n name\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Invalid String values/Int into String", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n stringArgField(stringArg: 1)\n }\n }\n ", - "errors": [ - { - "message": "Argument \"stringArg\" has invalid value 1.\nExpected type \"String\", found 1.", - "locations": [ - { - "line": 4, - "column": 39 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid String values/Float into String", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n stringArgField(stringArg: 1.0)\n }\n }\n ", - "errors": [ - { - "message": "Argument \"stringArg\" has invalid value 1.0.\nExpected type \"String\", found 1.0.", - "locations": [ - { - "line": 4, - "column": 39 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid String values/Boolean into String", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n stringArgField(stringArg: true)\n }\n }\n ", - "errors": [ - { - "message": "Argument \"stringArg\" has invalid value true.\nExpected type \"String\", found true.", - "locations": [ - { - "line": 4, - "column": 39 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid String values/Unquoted String into String", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n stringArgField(stringArg: BAR)\n }\n }\n ", - "errors": [ - { - "message": "Argument \"stringArg\" has invalid value BAR.\nExpected type \"String\", found BAR.", - "locations": [ - { - "line": 4, - "column": 39 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid Int values/String into Int", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n intArgField(intArg: \"3\")\n }\n }\n ", - "errors": [ - { - "message": "Argument \"intArg\" has invalid value \"3\".\nExpected type \"Int\", found \"3\".", - "locations": [ - { - "line": 4, - "column": 33 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid Int values/Big Int into Int", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n intArgField(intArg: 829384293849283498239482938)\n }\n }\n ", - "errors": [ - { - "message": "Argument \"intArg\" has invalid value 829384293849283498239482938.\nExpected type \"Int\", found 829384293849283498239482938.", - "locations": [ - { - "line": 4, - "column": 33 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid Int values/Unquoted String into Int", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n intArgField(intArg: FOO)\n }\n }\n ", - "errors": [ - { - "message": "Argument \"intArg\" has invalid value FOO.\nExpected type \"Int\", found FOO.", - "locations": [ - { - "line": 4, - "column": 33 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid Int values/Simple Float into Int", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n intArgField(intArg: 3.0)\n }\n }\n ", - "errors": [ - { - "message": "Argument \"intArg\" has invalid value 3.0.\nExpected type \"Int\", found 3.0.", - "locations": [ - { - "line": 4, - "column": 33 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid Int values/Float into Int", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n intArgField(intArg: 3.333)\n }\n }\n ", - "errors": [ - { - "message": "Argument \"intArg\" has invalid value 3.333.\nExpected type \"Int\", found 3.333.", - "locations": [ - { - "line": 4, - "column": 33 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid Float values/String into Float", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n floatArgField(floatArg: \"3.333\")\n }\n }\n ", - "errors": [ - { - "message": "Argument \"floatArg\" has invalid value \"3.333\".\nExpected type \"Float\", found \"3.333\".", - "locations": [ - { - "line": 4, - "column": 37 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid Float values/Boolean into Float", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n floatArgField(floatArg: true)\n }\n }\n ", - "errors": [ - { - "message": "Argument \"floatArg\" has invalid value true.\nExpected type \"Float\", found true.", - "locations": [ - { - "line": 4, - "column": 37 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid Float values/Unquoted into Float", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n floatArgField(floatArg: FOO)\n }\n }\n ", - "errors": [ - { - "message": "Argument \"floatArg\" has invalid value FOO.\nExpected type \"Float\", found FOO.", - "locations": [ - { - "line": 4, - "column": 37 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid Boolean value/Int into Boolean", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n booleanArgField(booleanArg: 2)\n }\n }\n ", - "errors": [ - { - "message": "Argument \"booleanArg\" has invalid value 2.\nExpected type \"Boolean\", found 2.", - "locations": [ - { - "line": 4, - "column": 41 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid Boolean value/Float into Boolean", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n booleanArgField(booleanArg: 1.0)\n }\n }\n ", - "errors": [ - { - "message": "Argument \"booleanArg\" has invalid value 1.0.\nExpected type \"Boolean\", found 1.0.", - "locations": [ - { - "line": 4, - "column": 41 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid Boolean value/String into Boolean", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n booleanArgField(booleanArg: \"true\")\n }\n }\n ", - "errors": [ - { - "message": "Argument \"booleanArg\" has invalid value \"true\".\nExpected type \"Boolean\", found \"true\".", - "locations": [ - { - "line": 4, - "column": 41 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid Boolean value/Unquoted into Boolean", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n booleanArgField(booleanArg: TRUE)\n }\n }\n ", - "errors": [ - { - "message": "Argument \"booleanArg\" has invalid value TRUE.\nExpected type \"Boolean\", found TRUE.", - "locations": [ - { - "line": 4, - "column": 41 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid ID value/Float into ID", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n idArgField(idArg: 1.0)\n }\n }\n ", - "errors": [ - { - "message": "Argument \"idArg\" has invalid value 1.0.\nExpected type \"ID\", found 1.0.", - "locations": [ - { - "line": 4, - "column": 31 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid ID value/Boolean into ID", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n idArgField(idArg: true)\n }\n }\n ", - "errors": [ - { - "message": "Argument \"idArg\" has invalid value true.\nExpected type \"ID\", found true.", - "locations": [ - { - "line": 4, - "column": 31 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid ID value/Unquoted into ID", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n idArgField(idArg: SOMETHING)\n }\n }\n ", - "errors": [ - { - "message": "Argument \"idArg\" has invalid value SOMETHING.\nExpected type \"ID\", found SOMETHING.", - "locations": [ - { - "line": 4, - "column": 31 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid Enum value/Int into Enum", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n dog {\n doesKnowCommand(dogCommand: 2)\n }\n }\n ", - "errors": [ - { - "message": "Argument \"dogCommand\" has invalid value 2.\nExpected type \"DogCommand\", found 2.", - "locations": [ - { - "line": 4, - "column": 41 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid Enum value/Float into Enum", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n dog {\n doesKnowCommand(dogCommand: 1.0)\n }\n }\n ", - "errors": [ - { - "message": "Argument \"dogCommand\" has invalid value 1.0.\nExpected type \"DogCommand\", found 1.0.", - "locations": [ - { - "line": 4, - "column": 41 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid Enum value/String into Enum", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n dog {\n doesKnowCommand(dogCommand: \"SIT\")\n }\n }\n ", - "errors": [ - { - "message": "Argument \"dogCommand\" has invalid value \"SIT\".\nExpected type \"DogCommand\", found \"SIT\".", - "locations": [ - { - "line": 4, - "column": 41 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid Enum value/Boolean into Enum", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n dog {\n doesKnowCommand(dogCommand: true)\n }\n }\n ", - "errors": [ - { - "message": "Argument \"dogCommand\" has invalid value true.\nExpected type \"DogCommand\", found true.", - "locations": [ - { - "line": 4, - "column": 41 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid Enum value/Unknown Enum Value into Enum", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n dog {\n doesKnowCommand(dogCommand: JUGGLE)\n }\n }\n ", - "errors": [ - { - "message": "Argument \"dogCommand\" has invalid value JUGGLE.\nExpected type \"DogCommand\", found JUGGLE.", - "locations": [ - { - "line": 4, - "column": 41 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid Enum value/Different case Enum Value into Enum", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n dog {\n doesKnowCommand(dogCommand: sit)\n }\n }\n ", - "errors": [ - { - "message": "Argument \"dogCommand\" has invalid value sit.\nExpected type \"DogCommand\", found sit.", - "locations": [ - { - "line": 4, - "column": 41 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Valid List value/Good list value", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n stringListArgField(stringListArg: [\"one\", null, \"two\"])\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid List value/Empty list value", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n stringListArgField(stringListArg: [])\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid List value/Null value", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n stringListArgField(stringListArg: null)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid List value/Single value into List", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n stringListArgField(stringListArg: \"one\")\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Invalid List value/Incorrect item type", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n stringListArgField(stringListArg: [\"one\", 2])\n }\n }\n ", - "errors": [ - { - "message": "Argument \"stringListArg\" has invalid value [\"one\", 2].\nIn element #1: Expected type \"String\", found 2.", - "locations": [ - { - "line": 4, - "column": 47 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid List value/Single value of incorrect type", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n stringListArgField(stringListArg: 1)\n }\n }\n ", - "errors": [ - { - "message": "Argument \"stringListArg\" has invalid value 1.\nExpected type \"String\", found 1.", - "locations": [ - { - "line": 4, - "column": 47 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Valid non-nullable value/Arg on optional arg", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n dog {\n isHousetrained(atOtherHomes: true)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid non-nullable value/No Arg on optional arg", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n dog {\n isHousetrained\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid non-nullable value/Multiple args", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n multipleReqs(req1: 1, req2: 2)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid non-nullable value/Multiple args reverse order", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n multipleReqs(req2: 2, req1: 1)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid non-nullable value/No args on multiple optional", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n multipleOpts\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid non-nullable value/One arg on multiple optional", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n multipleOpts(opt1: 1)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid non-nullable value/Second arg on multiple optional", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n multipleOpts(opt2: 1)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid non-nullable value/Multiple reqs on mixedList", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n multipleOptAndReq(req1: 3, req2: 4)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid non-nullable value/Multiple reqs and one opt on mixedList", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n multipleOptAndReq(req1: 3, req2: 4, opt1: 5)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid non-nullable value/All reqs and opts on mixedList", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n multipleOptAndReq(req1: 3, req2: 4, opt1: 5, opt2: 6)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Invalid non-nullable value/Incorrect value type", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n multipleReqs(req2: \"two\", req1: \"one\")\n }\n }\n ", - "errors": [ - { - "message": "Argument \"req2\" has invalid value \"two\".\nExpected type \"Int\", found \"two\".", - "locations": [ - { - "line": 4, - "column": 32 - } - ] - }, - { - "message": "Argument \"req1\" has invalid value \"one\".\nExpected type \"Int\", found \"one\".", - "locations": [ - { - "line": 4, - "column": 45 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid non-nullable value/Incorrect value and missing argument", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n multipleReqs(req1: \"one\")\n }\n }\n ", - "errors": [ - { - "message": "Argument \"req1\" has invalid value \"one\".\nExpected type \"Int\", found \"one\".", - "locations": [ - { - "line": 4, - "column": 32 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid non-nullable value/Null value", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n multipleReqs(req1: null)\n }\n }\n ", - "errors": [ - { - "message": "Argument \"req1\" has invalid value null.\nExpected \"Int!\", found null.", - "locations": [ - { - "line": 4, - "column": 32 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Valid input object value/Optional arg, despite required field in type", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n complexArgField\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid input object value/Partial object, only required", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n complexArgField(complexArg: { requiredField: true })\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid input object value/Partial object, required field can be falsey", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n complexArgField(complexArg: { requiredField: false })\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid input object value/Partial object, including required", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n complexArgField(complexArg: { requiredField: true, intField: 4 })\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid input object value/Full object", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n complexArgField(complexArg: {\n requiredField: true,\n intField: 4,\n stringField: \"foo\",\n booleanField: false,\n stringListField: [\"one\", \"two\"]\n })\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Valid input object value/Full object with fields in different order", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n complexArgField(complexArg: {\n stringListField: [\"one\", \"two\"],\n booleanField: false,\n requiredField: true,\n stringField: \"foo\",\n intField: 4,\n })\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Invalid input object value/Partial object, missing required", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n complexArgField(complexArg: { intField: 4 })\n }\n }\n ", - "errors": [ - { - "message": "Argument \"complexArg\" has invalid value {intField: 4}.\nIn field \"requiredField\": Expected \"Boolean!\", found null.", - "locations": [ - { - "line": 4, - "column": 41 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid input object value/Partial object, invalid field type", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n complexArgField(complexArg: {\n stringListField: [\"one\", 2],\n requiredField: true,\n })\n }\n }\n ", - "errors": [ - { - "message": "Argument \"complexArg\" has invalid value {stringListField: [\"one\", 2], requiredField: true}.\nIn field \"stringListField\": In element #1: Expected type \"String\", found 2.", - "locations": [ - { - "line": 4, - "column": 41 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Invalid input object value/Partial object, unknown field arg", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n complicatedArgs {\n complexArgField(complexArg: {\n requiredField: true,\n unknownField: \"value\"\n })\n }\n }\n ", - "errors": [ - { - "message": "Argument \"complexArg\" has invalid value {requiredField: true, unknownField: \"value\"}.\nIn field \"unknownField\": Unknown field.", - "locations": [ - { - "line": 4, - "column": 41 - } - ] - } - ] - }, - { - "name": "Validate: Argument values of correct type/Directive arguments/with directives of valid types", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n dog @include(if: true) {\n name\n }\n human @skip(if: false) {\n name\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Argument values of correct type/Directive arguments/with directive with incorrect types", - "rule": "ArgumentsOfCorrectType", - "schema": 0, - "query": "\n {\n dog @include(if: \"yes\") {\n name @skip(if: ENUM)\n }\n }\n ", - "errors": [ - { - "message": "Argument \"if\" has invalid value \"yes\".\nExpected type \"Boolean\", found \"yes\".", - "locations": [ - { - "line": 3, - "column": 28 - } - ] - }, - { - "message": "Argument \"if\" has invalid value ENUM.\nExpected type \"Boolean\", found ENUM.", - "locations": [ - { - "line": 4, - "column": 28 - } - ] - } - ] - }, - { - "name": "Validate: Variable default values of correct type/variables with no default values", - "rule": "DefaultValuesOfCorrectType", - "schema": 0, - "query": "\n query NullableValues($a: Int, $b: String, $c: ComplexInput) {\n dog { name }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Variable default values of correct type/required variables without default values", - "rule": "DefaultValuesOfCorrectType", - "schema": 0, - "query": "\n query RequiredValues($a: Int!, $b: String!) {\n dog { name }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Variable default values of correct type/variables with valid default values", - "rule": "DefaultValuesOfCorrectType", - "schema": 0, - "query": "\n query WithDefaultValues(\n $a: Int = 1,\n $b: String = \"ok\",\n $c: ComplexInput = { requiredField: true, intField: 3 }\n ) {\n dog { name }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Variable default values of correct type/variables with valid default null values", - "rule": "DefaultValuesOfCorrectType", - "schema": 0, - "query": "\n query WithDefaultValues(\n $a: Int = null,\n $b: String = null,\n $c: ComplexInput = { requiredField: true, intField: null }\n ) {\n dog { name }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Variable default values of correct type/variables with invalid default null values", - "rule": "DefaultValuesOfCorrectType", - "schema": 0, - "query": "\n query WithDefaultValues(\n $a: Int! = null,\n $b: String! = null,\n $c: ComplexInput = { requiredField: null, intField: null }\n ) {\n dog { name }\n }\n ", - "errors": [ - { - "message": "Variable \"$a\" of type \"Int!\" is required and will not use the default value. Perhaps you meant to use type \"Int\".", - "locations": [ - { - "line": 3, - "column": 20 - } - ] - }, - { - "message": "Variable \"$a\" of type \"Int!\" has invalid default value null.\nExpected \"Int!\", found null.", - "locations": [ - { - "line": 3, - "column": 20 - } - ] - }, - { - "message": "Variable \"$b\" of type \"String!\" is required and will not use the default value. Perhaps you meant to use type \"String\".", - "locations": [ - { - "line": 4, - "column": 23 - } - ] - }, - { - "message": "Variable \"$b\" of type \"String!\" has invalid default value null.\nExpected \"String!\", found null.", - "locations": [ - { - "line": 4, - "column": 23 - } - ] - }, - { - "message": "Variable \"$c\" of type \"ComplexInput\" has invalid default value {requiredField: null, intField: null}.\nIn field \"requiredField\": Expected \"Boolean!\", found null.", - "locations": [ - { - "line": 5, - "column": 28 - } - ] - } - ] - }, - { - "name": "Validate: Variable default values of correct type/no required variables with default values", - "rule": "DefaultValuesOfCorrectType", - "schema": 0, - "query": "\n query UnreachableDefaultValues($a: Int! = 3, $b: String! = \"default\") {\n dog { name }\n }\n ", - "errors": [ - { - "message": "Variable \"$a\" of type \"Int!\" is required and will not use the default value. Perhaps you meant to use type \"Int\".", - "locations": [ - { - "line": 2, - "column": 49 - } - ] - }, - { - "message": "Variable \"$b\" of type \"String!\" is required and will not use the default value. Perhaps you meant to use type \"String\".", - "locations": [ - { - "line": 2, - "column": 66 - } - ] - } - ] - }, - { - "name": "Validate: Variable default values of correct type/variables with invalid default values", - "rule": "DefaultValuesOfCorrectType", - "schema": 0, - "query": "\n query InvalidDefaultValues(\n $a: Int = \"one\",\n $b: String = 4,\n $c: ComplexInput = \"notverycomplex\"\n ) {\n dog { name }\n }\n ", - "errors": [ - { - "message": "Variable \"$a\" of type \"Int\" has invalid default value \"one\".\nExpected type \"Int\", found \"one\".", - "locations": [ - { - "line": 3, - "column": 19 - } - ] - }, - { - "message": "Variable \"$b\" of type \"String\" has invalid default value 4.\nExpected type \"String\", found 4.", - "locations": [ - { - "line": 4, - "column": 22 - } - ] - }, - { - "message": "Variable \"$c\" of type \"ComplexInput\" has invalid default value \"notverycomplex\".\nExpected \"ComplexInput\", found not an object.", - "locations": [ - { - "line": 5, - "column": 28 - } - ] - } - ] - }, - { - "name": "Validate: Variable default values of correct type/complex variables missing required field", - "rule": "DefaultValuesOfCorrectType", - "schema": 0, - "query": "\n query MissingRequiredField($a: ComplexInput = {intField: 3}) {\n dog { name }\n }\n ", - "errors": [ - { - "message": "Variable \"$a\" of type \"ComplexInput\" has invalid default value {intField: 3}.\nIn field \"requiredField\": Expected \"Boolean!\", found null.", - "locations": [ - { - "line": 2, - "column": 53 - } - ] - } - ] - }, - { - "name": "Validate: Variable default values of correct type/list variables with invalid item", - "rule": "DefaultValuesOfCorrectType", - "schema": 0, - "query": "\n query InvalidItem($a: [String] = [\"one\", 2]) {\n dog { name }\n }\n ", - "errors": [ - { - "message": "Variable \"$a\" of type \"[String]\" has invalid default value [\"one\", 2].\nIn element #1: Expected type \"String\", found 2.", - "locations": [ - { - "line": 2, - "column": 40 - } - ] - } - ] - }, - { - "name": "Validate: Fields on correct type/Object field selection", - "rule": "FieldsOnCorrectType", - "schema": 0, - "query": "\n fragment objectFieldSelection on Dog {\n __typename\n name\n }\n ", - "errors": [] - }, - { - "name": "Validate: Fields on correct type/Aliased object field selection", - "rule": "FieldsOnCorrectType", - "schema": 0, - "query": "\n fragment aliasedObjectFieldSelection on Dog {\n tn : __typename\n otherName : name\n }\n ", - "errors": [] - }, - { - "name": "Validate: Fields on correct type/Interface field selection", - "rule": "FieldsOnCorrectType", - "schema": 0, - "query": "\n fragment interfaceFieldSelection on Pet {\n __typename\n name\n }\n ", - "errors": [] - }, - { - "name": "Validate: Fields on correct type/Aliased interface field selection", - "rule": "FieldsOnCorrectType", - "schema": 0, - "query": "\n fragment interfaceFieldSelection on Pet {\n otherName : name\n }\n ", - "errors": [] - }, - { - "name": "Validate: Fields on correct type/Lying alias selection", - "rule": "FieldsOnCorrectType", - "schema": 0, - "query": "\n fragment lyingAliasSelection on Dog {\n name : nickname\n }\n ", - "errors": [] - }, - { - "name": "Validate: Fields on correct type/Ignores fields on unknown type", - "rule": "FieldsOnCorrectType", - "schema": 0, - "query": "\n fragment unknownSelection on UnknownType {\n unknownField\n }\n ", - "errors": [] - }, - { - "name": "Validate: Fields on correct type/reports errors when type is known again", - "rule": "FieldsOnCorrectType", - "schema": 0, - "query": "\n fragment typeKnownAgain on Pet {\n unknown_pet_field {\n ... on Cat {\n unknown_cat_field\n }\n }\n }", - "errors": [ - { - "message": "Cannot query field \"unknown_pet_field\" on type \"Pet\".", - "locations": [ - { - "line": 3, - "column": 9 - } - ] - }, - { - "message": "Cannot query field \"unknown_cat_field\" on type \"Cat\".", - "locations": [ - { - "line": 5, - "column": 13 - } - ] - } - ] - }, - { - "name": "Validate: Fields on correct type/Field not defined on fragment", - "rule": "FieldsOnCorrectType", - "schema": 0, - "query": "\n fragment fieldNotDefined on Dog {\n meowVolume\n }", - "errors": [ - { - "message": "Cannot query field \"meowVolume\" on type \"Dog\". Did you mean \"barkVolume\"?", - "locations": [ - { - "line": 3, - "column": 9 - } - ] - } - ] - }, - { - "name": "Validate: Fields on correct type/Ignores deeply unknown field", - "rule": "FieldsOnCorrectType", - "schema": 0, - "query": "\n fragment deepFieldNotDefined on Dog {\n unknown_field {\n deeper_unknown_field\n }\n }", - "errors": [ - { - "message": "Cannot query field \"unknown_field\" on type \"Dog\".", - "locations": [ - { - "line": 3, - "column": 9 - } - ] - } - ] - }, - { - "name": "Validate: Fields on correct type/Sub-field not defined", - "rule": "FieldsOnCorrectType", - "schema": 0, - "query": "\n fragment subFieldNotDefined on Human {\n pets {\n unknown_field\n }\n }", - "errors": [ - { - "message": "Cannot query field \"unknown_field\" on type \"Pet\".", - "locations": [ - { - "line": 4, - "column": 11 - } - ] - } - ] - }, - { - "name": "Validate: Fields on correct type/Field not defined on inline fragment", - "rule": "FieldsOnCorrectType", - "schema": 0, - "query": "\n fragment fieldNotDefined on Pet {\n ... on Dog {\n meowVolume\n }\n }", - "errors": [ - { - "message": "Cannot query field \"meowVolume\" on type \"Dog\". Did you mean \"barkVolume\"?", - "locations": [ - { - "line": 4, - "column": 11 - } - ] - } - ] - }, - { - "name": "Validate: Fields on correct type/Aliased field target not defined", - "rule": "FieldsOnCorrectType", - "schema": 0, - "query": "\n fragment aliasedFieldTargetNotDefined on Dog {\n volume : mooVolume\n }", - "errors": [ - { - "message": "Cannot query field \"mooVolume\" on type \"Dog\". Did you mean \"barkVolume\"?", - "locations": [ - { - "line": 3, - "column": 9 - } - ] - } - ] - }, - { - "name": "Validate: Fields on correct type/Aliased lying field target not defined", - "rule": "FieldsOnCorrectType", - "schema": 0, - "query": "\n fragment aliasedLyingFieldTargetNotDefined on Dog {\n barkVolume : kawVolume\n }", - "errors": [ - { - "message": "Cannot query field \"kawVolume\" on type \"Dog\". Did you mean \"barkVolume\"?", - "locations": [ - { - "line": 3, - "column": 9 - } - ] - } - ] - }, - { - "name": "Validate: Fields on correct type/Not defined on interface", - "rule": "FieldsOnCorrectType", - "schema": 0, - "query": "\n fragment notDefinedOnInterface on Pet {\n tailLength\n }", - "errors": [ - { - "message": "Cannot query field \"tailLength\" on type \"Pet\".", - "locations": [ - { - "line": 3, - "column": 9 - } - ] - } - ] - }, - { - "name": "Validate: Fields on correct type/Defined on implementors but not on interface", - "rule": "FieldsOnCorrectType", - "schema": 0, - "query": "\n fragment definedOnImplementorsButNotInterface on Pet {\n nickname\n }", - "errors": [ - { - "message": "Cannot query field \"nickname\" on type \"Pet\".", - "locations": [ - { - "line": 3, - "column": 9 - } - ] - } - ] - }, - { - "name": "Validate: Fields on correct type/Meta field selection on union", - "rule": "FieldsOnCorrectType", - "schema": 0, - "query": "\n fragment directFieldSelectionOnUnion on CatOrDog {\n __typename\n }", - "errors": [] - }, - { - "name": "Validate: Fields on correct type/Direct field selection on union", - "rule": "FieldsOnCorrectType", - "schema": 0, - "query": "\n fragment directFieldSelectionOnUnion on CatOrDog {\n directField\n }", - "errors": [ - { - "message": "Cannot query field \"directField\" on type \"CatOrDog\".", - "locations": [ - { - "line": 3, - "column": 9 - } - ] - } - ] - }, - { - "name": "Validate: Fields on correct type/Defined on implementors queried on union", - "rule": "FieldsOnCorrectType", - "schema": 0, - "query": "\n fragment definedOnImplementorsQueriedOnUnion on CatOrDog {\n name\n }", - "errors": [ - { - "message": "Cannot query field \"name\" on type \"CatOrDog\".", - "locations": [ - { - "line": 3, - "column": 9 - } - ] - } - ] - }, - { - "name": "Validate: Fields on correct type/valid field in inline fragment", - "rule": "FieldsOnCorrectType", - "schema": 0, - "query": "\n fragment objectFieldSelection on Pet {\n ... on Dog {\n name\n }\n ... {\n name\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Fragments on composite types/object is valid fragment type", - "rule": "FragmentsOnCompositeTypes", - "schema": 0, - "query": "\n fragment validFragment on Dog {\n barks\n }\n ", - "errors": [] - }, - { - "name": "Validate: Fragments on composite types/interface is valid fragment type", - "rule": "FragmentsOnCompositeTypes", - "schema": 0, - "query": "\n fragment validFragment on Pet {\n name\n }\n ", - "errors": [] - }, - { - "name": "Validate: Fragments on composite types/object is valid inline fragment type", - "rule": "FragmentsOnCompositeTypes", - "schema": 0, - "query": "\n fragment validFragment on Pet {\n ... on Dog {\n barks\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Fragments on composite types/inline fragment without type is valid", - "rule": "FragmentsOnCompositeTypes", - "schema": 0, - "query": "\n fragment validFragment on Pet {\n ... {\n name\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Fragments on composite types/union is valid fragment type", - "rule": "FragmentsOnCompositeTypes", - "schema": 0, - "query": "\n fragment validFragment on CatOrDog {\n __typename\n }\n ", - "errors": [] - }, - { - "name": "Validate: Fragments on composite types/scalar is invalid fragment type", - "rule": "FragmentsOnCompositeTypes", - "schema": 0, - "query": "\n fragment scalarFragment on Boolean {\n bad\n }\n ", - "errors": [ - { - "message": "Fragment \"scalarFragment\" cannot condition on non composite type \"Boolean\".", - "locations": [ - { - "line": 2, - "column": 34 - } - ] - } - ] - }, - { - "name": "Validate: Fragments on composite types/enum is invalid fragment type", - "rule": "FragmentsOnCompositeTypes", - "schema": 0, - "query": "\n fragment scalarFragment on FurColor {\n bad\n }\n ", - "errors": [ - { - "message": "Fragment \"scalarFragment\" cannot condition on non composite type \"FurColor\".", - "locations": [ - { - "line": 2, - "column": 34 - } - ] - } - ] - }, - { - "name": "Validate: Fragments on composite types/input object is invalid fragment type", - "rule": "FragmentsOnCompositeTypes", - "schema": 0, - "query": "\n fragment inputFragment on ComplexInput {\n stringField\n }\n ", - "errors": [ - { - "message": "Fragment \"inputFragment\" cannot condition on non composite type \"ComplexInput\".", - "locations": [ - { - "line": 2, - "column": 33 - } - ] - } - ] - }, - { - "name": "Validate: Fragments on composite types/scalar is invalid inline fragment type", - "rule": "FragmentsOnCompositeTypes", - "schema": 0, - "query": "\n fragment invalidFragment on Pet {\n ... on String {\n barks\n }\n }\n ", - "errors": [ - { - "message": "Fragment cannot condition on non composite type \"String\".", - "locations": [ - { - "line": 3, - "column": 16 - } - ] - } - ] - }, - { - "name": "Validate: Known argument names/single arg is known", - "rule": "KnownArgumentNames", - "schema": 0, - "query": "\n fragment argOnRequiredArg on Dog {\n doesKnowCommand(dogCommand: SIT)\n }\n ", - "errors": [] - }, - { - "name": "Validate: Known argument names/multiple args are known", - "rule": "KnownArgumentNames", - "schema": 0, - "query": "\n fragment multipleArgs on ComplicatedArgs {\n multipleReqs(req1: 1, req2: 2)\n }\n ", - "errors": [] - }, - { - "name": "Validate: Known argument names/ignores args of unknown fields", - "rule": "KnownArgumentNames", - "schema": 0, - "query": "\n fragment argOnUnknownField on Dog {\n unknownField(unknownArg: SIT)\n }\n ", - "errors": [] - }, - { - "name": "Validate: Known argument names/multiple args in reverse order are known", - "rule": "KnownArgumentNames", - "schema": 0, - "query": "\n fragment multipleArgsReverseOrder on ComplicatedArgs {\n multipleReqs(req2: 2, req1: 1)\n }\n ", - "errors": [] - }, - { - "name": "Validate: Known argument names/no args on optional arg", - "rule": "KnownArgumentNames", - "schema": 0, - "query": "\n fragment noArgOnOptionalArg on Dog {\n isHousetrained\n }\n ", - "errors": [] - }, - { - "name": "Validate: Known argument names/args are known deeply", - "rule": "KnownArgumentNames", - "schema": 0, - "query": "\n {\n dog {\n doesKnowCommand(dogCommand: SIT)\n }\n human {\n pet {\n ... on Dog {\n doesKnowCommand(dogCommand: SIT)\n }\n }\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Known argument names/directive args are known", - "rule": "KnownArgumentNames", - "schema": 0, - "query": "\n {\n dog @skip(if: true)\n }\n ", - "errors": [] - }, - { - "name": "Validate: Known argument names/undirective args are invalid", - "rule": "KnownArgumentNames", - "schema": 0, - "query": "\n {\n dog @skip(unless: true)\n }\n ", - "errors": [ - { - "message": "Unknown argument \"unless\" on directive \"@skip\".", - "locations": [ - { - "line": 3, - "column": 19 - } - ] - } - ] - }, - { - "name": "Validate: Known argument names/invalid arg name", - "rule": "KnownArgumentNames", - "schema": 0, - "query": "\n fragment invalidArgName on Dog {\n doesKnowCommand(unknown: true)\n }\n ", - "errors": [ - { - "message": "Unknown argument \"unknown\" on field \"doesKnowCommand\" of type \"Dog\".", - "locations": [ - { - "line": 3, - "column": 25 - } - ] - } - ] - }, - { - "name": "Validate: Known argument names/unknown args amongst known args", - "rule": "KnownArgumentNames", - "schema": 0, - "query": "\n fragment oneGoodArgOneInvalidArg on Dog {\n doesKnowCommand(whoknows: 1, dogCommand: SIT, unknown: true)\n }\n ", - "errors": [ - { - "message": "Unknown argument \"whoknows\" on field \"doesKnowCommand\" of type \"Dog\".", - "locations": [ - { - "line": 3, - "column": 25 - } - ] - }, - { - "message": "Unknown argument \"unknown\" on field \"doesKnowCommand\" of type \"Dog\".", - "locations": [ - { - "line": 3, - "column": 55 - } - ] - } - ] - }, - { - "name": "Validate: Known argument names/unknown args deeply", - "rule": "KnownArgumentNames", - "schema": 0, - "query": "\n {\n dog {\n doesKnowCommand(unknown: true)\n }\n human {\n pet {\n ... on Dog {\n doesKnowCommand(unknown: true)\n }\n }\n }\n }\n ", - "errors": [ - { - "message": "Unknown argument \"unknown\" on field \"doesKnowCommand\" of type \"Dog\".", - "locations": [ - { - "line": 4, - "column": 27 - } - ] - }, - { - "message": "Unknown argument \"unknown\" on field \"doesKnowCommand\" of type \"Dog\".", - "locations": [ - { - "line": 9, - "column": 31 - } - ] - } - ] - }, - { - "name": "Validate: Known directives/with no directives", - "rule": "KnownDirectives", - "schema": 0, - "query": "\n query Foo {\n name\n ...Frag\n }\n\n fragment Frag on Dog {\n name\n }\n ", - "errors": [] - }, - { - "name": "Validate: Known directives/with known directives", - "rule": "KnownDirectives", - "schema": 0, - "query": "\n {\n dog @include(if: true) {\n name\n }\n human @skip(if: false) {\n name\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Known directives/with unknown directive", - "rule": "KnownDirectives", - "schema": 0, - "query": "\n {\n dog @unknown(directive: \"value\") {\n name\n }\n }\n ", - "errors": [ - { - "message": "Unknown directive \"unknown\".", - "locations": [ - { - "line": 3, - "column": 13 - } - ] - } - ] - }, - { - "name": "Validate: Known directives/with many unknown directives", - "rule": "KnownDirectives", - "schema": 0, - "query": "\n {\n dog @unknown(directive: \"value\") {\n name\n }\n human @unknown(directive: \"value\") {\n name\n pets @unknown(directive: \"value\") {\n name\n }\n }\n }\n ", - "errors": [ - { - "message": "Unknown directive \"unknown\".", - "locations": [ - { - "line": 3, - "column": 13 - } - ] - }, - { - "message": "Unknown directive \"unknown\".", - "locations": [ - { - "line": 6, - "column": 15 - } - ] - }, - { - "message": "Unknown directive \"unknown\".", - "locations": [ - { - "line": 8, - "column": 16 - } - ] - } - ] - }, - { - "name": "Validate: Known directives/with well placed directives", - "rule": "KnownDirectives", - "schema": 0, - "query": "\n query Foo @onQuery {\n name @include(if: true)\n ...Frag @include(if: true)\n skippedField @skip(if: true)\n ...SkippedFrag @skip(if: true)\n }\n\n mutation Bar @onMutation {\n someField\n }\n ", - "errors": [] - }, - { - "name": "Validate: Known directives/with misplaced directives", - "rule": "KnownDirectives", - "schema": 0, - "query": "\n query Foo @include(if: true) {\n name @onQuery\n ...Frag @onQuery\n }\n\n mutation Bar @onQuery {\n someField\n }\n ", - "errors": [ - { - "message": "Directive \"include\" may not be used on QUERY.", - "locations": [ - { - "line": 2, - "column": 17 - } - ] - }, - { - "message": "Directive \"onQuery\" may not be used on FIELD.", - "locations": [ - { - "line": 3, - "column": 14 - } - ] - }, - { - "message": "Directive \"onQuery\" may not be used on FRAGMENT_SPREAD.", - "locations": [ - { - "line": 4, - "column": 17 - } - ] - }, - { - "message": "Directive \"onQuery\" may not be used on MUTATION.", - "locations": [ - { - "line": 7, - "column": 20 - } - ] - } - ] - }, - { - "name": "Validate: Known fragment names/known fragment names are valid", - "rule": "KnownFragmentNames", - "schema": 0, - "query": "\n {\n human(id: 4) {\n ...HumanFields1\n ... on Human {\n ...HumanFields2\n }\n ... {\n name\n }\n }\n }\n fragment HumanFields1 on Human {\n name\n ...HumanFields3\n }\n fragment HumanFields2 on Human {\n name\n }\n fragment HumanFields3 on Human {\n name\n }\n ", - "errors": [] - }, - { - "name": "Validate: Known fragment names/unknown fragment names are invalid", - "rule": "KnownFragmentNames", - "schema": 0, - "query": "\n {\n human(id: 4) {\n ...UnknownFragment1\n ... on Human {\n ...UnknownFragment2\n }\n }\n }\n fragment HumanFields on Human {\n name\n ...UnknownFragment3\n }\n ", - "errors": [ - { - "message": "Unknown fragment \"UnknownFragment1\".", - "locations": [ - { - "line": 4, - "column": 14 - } - ] - }, - { - "message": "Unknown fragment \"UnknownFragment2\".", - "locations": [ - { - "line": 6, - "column": 16 - } - ] - }, - { - "message": "Unknown fragment \"UnknownFragment3\".", - "locations": [ - { - "line": 12, - "column": 12 - } - ] - } - ] - }, - { - "name": "Validate: Known type names/known type names are valid", - "rule": "KnownTypeNames", - "schema": 0, - "query": "\n query Foo($var: String, $required: [String!]!) {\n user(id: 4) {\n pets { ... on Pet { name }, ...PetFields, ... { name } }\n }\n }\n fragment PetFields on Pet {\n name\n }\n ", - "errors": [] - }, - { - "name": "Validate: Known type names/unknown type names are invalid", - "rule": "KnownTypeNames", - "schema": 0, - "query": "\n query Foo($var: JumbledUpLetters) {\n user(id: 4) {\n name\n pets { ... on Badger { name }, ...PetFields }\n }\n }\n fragment PetFields on Peettt {\n name\n }\n ", - "errors": [ - { - "message": "Unknown type \"JumbledUpLetters\".", - "locations": [ - { - "line": 2, - "column": 23 - } - ] - }, - { - "message": "Unknown type \"Badger\".", - "locations": [ - { - "line": 5, - "column": 25 - } - ] - }, - { - "message": "Unknown type \"Peettt\".", - "locations": [ - { - "line": 8, - "column": 29 - } - ] - } - ] - }, - { - "name": "Validate: Anonymous operation must be alone/no operations", - "rule": "LoneAnonymousOperation", - "schema": 0, - "query": "\n fragment fragA on Type {\n field\n }\n ", - "errors": [] - }, - { - "name": "Validate: Anonymous operation must be alone/one anon operation", - "rule": "LoneAnonymousOperation", - "schema": 0, - "query": "\n {\n field\n }\n ", - "errors": [] - }, - { - "name": "Validate: Anonymous operation must be alone/multiple named operations", - "rule": "LoneAnonymousOperation", - "schema": 0, - "query": "\n query Foo {\n field\n }\n\n query Bar {\n field\n }\n ", - "errors": [] - }, - { - "name": "Validate: Anonymous operation must be alone/anon operation with fragment", - "rule": "LoneAnonymousOperation", - "schema": 0, - "query": "\n {\n ...Foo\n }\n fragment Foo on Type {\n field\n }\n ", - "errors": [] - }, - { - "name": "Validate: Anonymous operation must be alone/multiple anon operations", - "rule": "LoneAnonymousOperation", - "schema": 0, - "query": "\n {\n fieldA\n }\n {\n fieldB\n }\n ", - "errors": [ - { - "message": "This anonymous operation must be the only defined operation.", - "locations": [ - { - "line": 2, - "column": 7 - } - ] - }, - { - "message": "This anonymous operation must be the only defined operation.", - "locations": [ - { - "line": 5, - "column": 7 - } - ] - } - ] - }, - { - "name": "Validate: Anonymous operation must be alone/anon operation with a mutation", - "rule": "LoneAnonymousOperation", - "schema": 0, - "query": "\n {\n fieldA\n }\n mutation Foo {\n fieldB\n }\n ", - "errors": [ - { - "message": "This anonymous operation must be the only defined operation.", - "locations": [ - { - "line": 2, - "column": 7 - } - ] - } - ] - }, - { - "name": "Validate: Anonymous operation must be alone/anon operation with a subscription", - "rule": "LoneAnonymousOperation", - "schema": 0, - "query": "\n {\n fieldA\n }\n subscription Foo {\n fieldB\n }\n ", - "errors": [ - { - "message": "This anonymous operation must be the only defined operation.", - "locations": [ - { - "line": 2, - "column": 7 - } - ] - } - ] - }, - { - "name": "Validate: No circular fragment spreads/single reference is valid", - "rule": "NoFragmentCycles", - "schema": 0, - "query": "\n fragment fragA on Dog { ...fragB }\n fragment fragB on Dog { name }\n ", - "errors": [] - }, - { - "name": "Validate: No circular fragment spreads/spreading twice is not circular", - "rule": "NoFragmentCycles", - "schema": 0, - "query": "\n fragment fragA on Dog { ...fragB, ...fragB }\n fragment fragB on Dog { name }\n ", - "errors": [] - }, - { - "name": "Validate: No circular fragment spreads/spreading twice indirectly is not circular", - "rule": "NoFragmentCycles", - "schema": 0, - "query": "\n fragment fragA on Dog { ...fragB, ...fragC }\n fragment fragB on Dog { ...fragC }\n fragment fragC on Dog { name }\n ", - "errors": [] - }, - { - "name": "Validate: No circular fragment spreads/double spread within abstract types", - "rule": "NoFragmentCycles", - "schema": 0, - "query": "\n fragment nameFragment on Pet {\n ... on Dog { name }\n ... on Cat { name }\n }\n\n fragment spreadsInAnon on Pet {\n ... on Dog { ...nameFragment }\n ... on Cat { ...nameFragment }\n }\n ", - "errors": [] - }, - { - "name": "Validate: No circular fragment spreads/does not false positive on unknown fragment", - "rule": "NoFragmentCycles", - "schema": 0, - "query": "\n fragment nameFragment on Pet {\n ...UnknownFragment\n }\n ", - "errors": [] - }, - { - "name": "Validate: No circular fragment spreads/spreading recursively within field fails", - "rule": "NoFragmentCycles", - "schema": 0, - "query": "\n fragment fragA on Human { relatives { ...fragA } },\n ", - "errors": [ - { - "message": "Cannot spread fragment \"fragA\" within itself.", - "locations": [ - { - "line": 2, - "column": 45 - } - ] - } - ] - }, - { - "name": "Validate: No circular fragment spreads/no spreading itself directly", - "rule": "NoFragmentCycles", - "schema": 0, - "query": "\n fragment fragA on Dog { ...fragA }\n ", - "errors": [ - { - "message": "Cannot spread fragment \"fragA\" within itself.", - "locations": [ - { - "line": 2, - "column": 31 - } - ] - } - ] - }, - { - "name": "Validate: No circular fragment spreads/no spreading itself directly within inline fragment", - "rule": "NoFragmentCycles", - "schema": 0, - "query": "\n fragment fragA on Pet {\n ... on Dog {\n ...fragA\n }\n }\n ", - "errors": [ - { - "message": "Cannot spread fragment \"fragA\" within itself.", - "locations": [ - { - "line": 4, - "column": 11 - } - ] - } - ] - }, - { - "name": "Validate: No circular fragment spreads/no spreading itself indirectly", - "rule": "NoFragmentCycles", - "schema": 0, - "query": "\n fragment fragA on Dog { ...fragB }\n fragment fragB on Dog { ...fragA }\n ", - "errors": [ - { - "message": "Cannot spread fragment \"fragA\" within itself via fragB.", - "locations": [ - { - "line": 2, - "column": 31 - }, - { - "line": 3, - "column": 31 - } - ] - } - ] - }, - { - "name": "Validate: No circular fragment spreads/no spreading itself indirectly reports opposite order", - "rule": "NoFragmentCycles", - "schema": 0, - "query": "\n fragment fragB on Dog { ...fragA }\n fragment fragA on Dog { ...fragB }\n ", - "errors": [ - { - "message": "Cannot spread fragment \"fragB\" within itself via fragA.", - "locations": [ - { - "line": 2, - "column": 31 - }, - { - "line": 3, - "column": 31 - } - ] - } - ] - }, - { - "name": "Validate: No circular fragment spreads/no spreading itself indirectly within inline fragment", - "rule": "NoFragmentCycles", - "schema": 0, - "query": "\n fragment fragA on Pet {\n ... on Dog {\n ...fragB\n }\n }\n fragment fragB on Pet {\n ... on Dog {\n ...fragA\n }\n }\n ", - "errors": [ - { - "message": "Cannot spread fragment \"fragA\" within itself via fragB.", - "locations": [ - { - "line": 4, - "column": 11 - }, - { - "line": 9, - "column": 11 - } - ] - } - ] - }, - { - "name": "Validate: No circular fragment spreads/no spreading itself deeply", - "rule": "NoFragmentCycles", - "schema": 0, - "query": "\n fragment fragA on Dog { ...fragB }\n fragment fragB on Dog { ...fragC }\n fragment fragC on Dog { ...fragO }\n fragment fragX on Dog { ...fragY }\n fragment fragY on Dog { ...fragZ }\n fragment fragZ on Dog { ...fragO }\n fragment fragO on Dog { ...fragP }\n fragment fragP on Dog { ...fragA, ...fragX }\n ", - "errors": [ - { - "message": "Cannot spread fragment \"fragA\" within itself via fragB, fragC, fragO, fragP.", - "locations": [ - { - "line": 2, - "column": 31 - }, - { - "line": 3, - "column": 31 - }, - { - "line": 4, - "column": 31 - }, - { - "line": 8, - "column": 31 - }, - { - "line": 9, - "column": 31 - } - ] - }, - { - "message": "Cannot spread fragment \"fragO\" within itself via fragP, fragX, fragY, fragZ.", - "locations": [ - { - "line": 8, - "column": 31 - }, - { - "line": 9, - "column": 41 - }, - { - "line": 5, - "column": 31 - }, - { - "line": 6, - "column": 31 - }, - { - "line": 7, - "column": 31 - } - ] - } - ] - }, - { - "name": "Validate: No circular fragment spreads/no spreading itself deeply two paths", - "rule": "NoFragmentCycles", - "schema": 0, - "query": "\n fragment fragA on Dog { ...fragB, ...fragC }\n fragment fragB on Dog { ...fragA }\n fragment fragC on Dog { ...fragA }\n ", - "errors": [ - { - "message": "Cannot spread fragment \"fragA\" within itself via fragB.", - "locations": [ - { - "line": 2, - "column": 31 - }, - { - "line": 3, - "column": 31 - } - ] - }, - { - "message": "Cannot spread fragment \"fragA\" within itself via fragC.", - "locations": [ - { - "line": 2, - "column": 41 - }, - { - "line": 4, - "column": 31 - } - ] - } - ] - }, - { - "name": "Validate: No circular fragment spreads/no spreading itself deeply two paths -- alt traverse order", - "rule": "NoFragmentCycles", - "schema": 0, - "query": "\n fragment fragA on Dog { ...fragC }\n fragment fragB on Dog { ...fragC }\n fragment fragC on Dog { ...fragA, ...fragB }\n ", - "errors": [ - { - "message": "Cannot spread fragment \"fragA\" within itself via fragC.", - "locations": [ - { - "line": 2, - "column": 31 - }, - { - "line": 4, - "column": 31 - } - ] - }, - { - "message": "Cannot spread fragment \"fragC\" within itself via fragB.", - "locations": [ - { - "line": 4, - "column": 41 - }, - { - "line": 3, - "column": 31 - } - ] - } - ] - }, - { - "name": "Validate: No circular fragment spreads/no spreading itself deeply and immediately", - "rule": "NoFragmentCycles", - "schema": 0, - "query": "\n fragment fragA on Dog { ...fragB }\n fragment fragB on Dog { ...fragB, ...fragC }\n fragment fragC on Dog { ...fragA, ...fragB }\n ", - "errors": [ - { - "message": "Cannot spread fragment \"fragB\" within itself.", - "locations": [ - { - "line": 3, - "column": 31 - } - ] - }, - { - "message": "Cannot spread fragment \"fragA\" within itself via fragB, fragC.", - "locations": [ - { - "line": 2, - "column": 31 - }, - { - "line": 3, - "column": 41 - }, - { - "line": 4, - "column": 31 - } - ] - }, - { - "message": "Cannot spread fragment \"fragB\" within itself via fragC.", - "locations": [ - { - "line": 3, - "column": 41 - }, - { - "line": 4, - "column": 41 - } - ] - } - ] - }, - { - "name": "Validate: No undefined variables/all variables defined", - "rule": "NoUndefinedVariables", - "schema": 0, - "query": "\n query Foo($a: String, $b: String, $c: String) {\n field(a: $a, b: $b, c: $c)\n }\n ", - "errors": [] - }, - { - "name": "Validate: No undefined variables/all variables deeply defined", - "rule": "NoUndefinedVariables", - "schema": 0, - "query": "\n query Foo($a: String, $b: String, $c: String) {\n field(a: $a) {\n field(b: $b) {\n field(c: $c)\n }\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: No undefined variables/all variables deeply in inline fragments defined", - "rule": "NoUndefinedVariables", - "schema": 0, - "query": "\n query Foo($a: String, $b: String, $c: String) {\n ... on Type {\n field(a: $a) {\n field(b: $b) {\n ... on Type {\n field(c: $c)\n }\n }\n }\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: No undefined variables/all variables in fragments deeply defined", - "rule": "NoUndefinedVariables", - "schema": 0, - "query": "\n query Foo($a: String, $b: String, $c: String) {\n ...FragA\n }\n fragment FragA on Type {\n field(a: $a) {\n ...FragB\n }\n }\n fragment FragB on Type {\n field(b: $b) {\n ...FragC\n }\n }\n fragment FragC on Type {\n field(c: $c)\n }\n ", - "errors": [] - }, - { - "name": "Validate: No undefined variables/variable within single fragment defined in multiple operations", - "rule": "NoUndefinedVariables", - "schema": 0, - "query": "\n query Foo($a: String) {\n ...FragA\n }\n query Bar($a: String) {\n ...FragA\n }\n fragment FragA on Type {\n field(a: $a)\n }\n ", - "errors": [] - }, - { - "name": "Validate: No undefined variables/variable within fragments defined in operations", - "rule": "NoUndefinedVariables", - "schema": 0, - "query": "\n query Foo($a: String) {\n ...FragA\n }\n query Bar($b: String) {\n ...FragB\n }\n fragment FragA on Type {\n field(a: $a)\n }\n fragment FragB on Type {\n field(b: $b)\n }\n ", - "errors": [] - }, - { - "name": "Validate: No undefined variables/variable within recursive fragment defined", - "rule": "NoUndefinedVariables", - "schema": 0, - "query": "\n query Foo($a: String) {\n ...FragA\n }\n fragment FragA on Type {\n field(a: $a) {\n ...FragA\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: No undefined variables/variable not defined", - "rule": "NoUndefinedVariables", - "schema": 0, - "query": "\n query Foo($a: String, $b: String, $c: String) {\n field(a: $a, b: $b, c: $c, d: $d)\n }\n ", - "errors": [ - { - "message": "Variable \"$d\" is not defined by operation \"Foo\".", - "locations": [ - { - "line": 3, - "column": 39 - }, - { - "line": 2, - "column": 7 - } - ] - } - ] - }, - { - "name": "Validate: No undefined variables/variable not defined by un-named query", - "rule": "NoUndefinedVariables", - "schema": 0, - "query": "\n {\n field(a: $a)\n }\n ", - "errors": [ - { - "message": "Variable \"$a\" is not defined.", - "locations": [ - { - "line": 3, - "column": 18 - }, - { - "line": 2, - "column": 7 - } - ] - } - ] - }, - { - "name": "Validate: No undefined variables/multiple variables not defined", - "rule": "NoUndefinedVariables", - "schema": 0, - "query": "\n query Foo($b: String) {\n field(a: $a, b: $b, c: $c)\n }\n ", - "errors": [ - { - "message": "Variable \"$a\" is not defined by operation \"Foo\".", - "locations": [ - { - "line": 3, - "column": 18 - }, - { - "line": 2, - "column": 7 - } - ] - }, - { - "message": "Variable \"$c\" is not defined by operation \"Foo\".", - "locations": [ - { - "line": 3, - "column": 32 - }, - { - "line": 2, - "column": 7 - } - ] - } - ] - }, - { - "name": "Validate: No undefined variables/variable in fragment not defined by un-named query", - "rule": "NoUndefinedVariables", - "schema": 0, - "query": "\n {\n ...FragA\n }\n fragment FragA on Type {\n field(a: $a)\n }\n ", - "errors": [ - { - "message": "Variable \"$a\" is not defined.", - "locations": [ - { - "line": 6, - "column": 18 - }, - { - "line": 2, - "column": 7 - } - ] - } - ] - }, - { - "name": "Validate: No undefined variables/variable in fragment not defined by operation", - "rule": "NoUndefinedVariables", - "schema": 0, - "query": "\n query Foo($a: String, $b: String) {\n ...FragA\n }\n fragment FragA on Type {\n field(a: $a) {\n ...FragB\n }\n }\n fragment FragB on Type {\n field(b: $b) {\n ...FragC\n }\n }\n fragment FragC on Type {\n field(c: $c)\n }\n ", - "errors": [ - { - "message": "Variable \"$c\" is not defined by operation \"Foo\".", - "locations": [ - { - "line": 16, - "column": 18 - }, - { - "line": 2, - "column": 7 - } - ] - } - ] - }, - { - "name": "Validate: No undefined variables/multiple variables in fragments not defined", - "rule": "NoUndefinedVariables", - "schema": 0, - "query": "\n query Foo($b: String) {\n ...FragA\n }\n fragment FragA on Type {\n field(a: $a) {\n ...FragB\n }\n }\n fragment FragB on Type {\n field(b: $b) {\n ...FragC\n }\n }\n fragment FragC on Type {\n field(c: $c)\n }\n ", - "errors": [ - { - "message": "Variable \"$a\" is not defined by operation \"Foo\".", - "locations": [ - { - "line": 6, - "column": 18 - }, - { - "line": 2, - "column": 7 - } - ] - }, - { - "message": "Variable \"$c\" is not defined by operation \"Foo\".", - "locations": [ - { - "line": 16, - "column": 18 - }, - { - "line": 2, - "column": 7 - } - ] - } - ] - }, - { - "name": "Validate: No undefined variables/single variable in fragment not defined by multiple operations", - "rule": "NoUndefinedVariables", - "schema": 0, - "query": "\n query Foo($a: String) {\n ...FragAB\n }\n query Bar($a: String) {\n ...FragAB\n }\n fragment FragAB on Type {\n field(a: $a, b: $b)\n }\n ", - "errors": [ - { - "message": "Variable \"$b\" is not defined by operation \"Foo\".", - "locations": [ - { - "line": 9, - "column": 25 - }, - { - "line": 2, - "column": 7 - } - ] - }, - { - "message": "Variable \"$b\" is not defined by operation \"Bar\".", - "locations": [ - { - "line": 9, - "column": 25 - }, - { - "line": 5, - "column": 7 - } - ] - } - ] - }, - { - "name": "Validate: No undefined variables/variables in fragment not defined by multiple operations", - "rule": "NoUndefinedVariables", - "schema": 0, - "query": "\n query Foo($b: String) {\n ...FragAB\n }\n query Bar($a: String) {\n ...FragAB\n }\n fragment FragAB on Type {\n field(a: $a, b: $b)\n }\n ", - "errors": [ - { - "message": "Variable \"$a\" is not defined by operation \"Foo\".", - "locations": [ - { - "line": 9, - "column": 18 - }, - { - "line": 2, - "column": 7 - } - ] - }, - { - "message": "Variable \"$b\" is not defined by operation \"Bar\".", - "locations": [ - { - "line": 9, - "column": 25 - }, - { - "line": 5, - "column": 7 - } - ] - } - ] - }, - { - "name": "Validate: No undefined variables/variable in fragment used by other operation", - "rule": "NoUndefinedVariables", - "schema": 0, - "query": "\n query Foo($b: String) {\n ...FragA\n }\n query Bar($a: String) {\n ...FragB\n }\n fragment FragA on Type {\n field(a: $a)\n }\n fragment FragB on Type {\n field(b: $b)\n }\n ", - "errors": [ - { - "message": "Variable \"$a\" is not defined by operation \"Foo\".", - "locations": [ - { - "line": 9, - "column": 18 - }, - { - "line": 2, - "column": 7 - } - ] - }, - { - "message": "Variable \"$b\" is not defined by operation \"Bar\".", - "locations": [ - { - "line": 12, - "column": 18 - }, - { - "line": 5, - "column": 7 - } - ] - } - ] - }, - { - "name": "Validate: No undefined variables/multiple undefined variables produce multiple errors", - "rule": "NoUndefinedVariables", - "schema": 0, - "query": "\n query Foo($b: String) {\n ...FragAB\n }\n query Bar($a: String) {\n ...FragAB\n }\n fragment FragAB on Type {\n field1(a: $a, b: $b)\n ...FragC\n field3(a: $a, b: $b)\n }\n fragment FragC on Type {\n field2(c: $c)\n }\n ", - "errors": [ - { - "message": "Variable \"$a\" is not defined by operation \"Foo\".", - "locations": [ - { - "line": 9, - "column": 19 - }, - { - "line": 2, - "column": 7 - } - ] - }, - { - "message": "Variable \"$a\" is not defined by operation \"Foo\".", - "locations": [ - { - "line": 11, - "column": 19 - }, - { - "line": 2, - "column": 7 - } - ] - }, - { - "message": "Variable \"$c\" is not defined by operation \"Foo\".", - "locations": [ - { - "line": 14, - "column": 19 - }, - { - "line": 2, - "column": 7 - } - ] - }, - { - "message": "Variable \"$b\" is not defined by operation \"Bar\".", - "locations": [ - { - "line": 9, - "column": 26 - }, - { - "line": 5, - "column": 7 - } - ] - }, - { - "message": "Variable \"$b\" is not defined by operation \"Bar\".", - "locations": [ - { - "line": 11, - "column": 26 - }, - { - "line": 5, - "column": 7 - } - ] - }, - { - "message": "Variable \"$c\" is not defined by operation \"Bar\".", - "locations": [ - { - "line": 14, - "column": 19 - }, - { - "line": 5, - "column": 7 - } - ] - } - ] - }, - { - "name": "Validate: No unused fragments/all fragment names are used", - "rule": "NoUnusedFragments", - "schema": 0, - "query": "\n {\n human(id: 4) {\n ...HumanFields1\n ... on Human {\n ...HumanFields2\n }\n }\n }\n fragment HumanFields1 on Human {\n name\n ...HumanFields3\n }\n fragment HumanFields2 on Human {\n name\n }\n fragment HumanFields3 on Human {\n name\n }\n ", - "errors": [] - }, - { - "name": "Validate: No unused fragments/all fragment names are used by multiple operations", - "rule": "NoUnusedFragments", - "schema": 0, - "query": "\n query Foo {\n human(id: 4) {\n ...HumanFields1\n }\n }\n query Bar {\n human(id: 4) {\n ...HumanFields2\n }\n }\n fragment HumanFields1 on Human {\n name\n ...HumanFields3\n }\n fragment HumanFields2 on Human {\n name\n }\n fragment HumanFields3 on Human {\n name\n }\n ", - "errors": [] - }, - { - "name": "Validate: No unused fragments/contains unknown fragments", - "rule": "NoUnusedFragments", - "schema": 0, - "query": "\n query Foo {\n human(id: 4) {\n ...HumanFields1\n }\n }\n query Bar {\n human(id: 4) {\n ...HumanFields2\n }\n }\n fragment HumanFields1 on Human {\n name\n ...HumanFields3\n }\n fragment HumanFields2 on Human {\n name\n }\n fragment HumanFields3 on Human {\n name\n }\n fragment Unused1 on Human {\n name\n }\n fragment Unused2 on Human {\n name\n }\n ", - "errors": [ - { - "message": "Fragment \"Unused1\" is never used.", - "locations": [ - { - "line": 22, - "column": 7 - } - ] - }, - { - "message": "Fragment \"Unused2\" is never used.", - "locations": [ - { - "line": 25, - "column": 7 - } - ] - } - ] - }, - { - "name": "Validate: No unused fragments/contains unknown fragments with ref cycle", - "rule": "NoUnusedFragments", - "schema": 0, - "query": "\n query Foo {\n human(id: 4) {\n ...HumanFields1\n }\n }\n query Bar {\n human(id: 4) {\n ...HumanFields2\n }\n }\n fragment HumanFields1 on Human {\n name\n ...HumanFields3\n }\n fragment HumanFields2 on Human {\n name\n }\n fragment HumanFields3 on Human {\n name\n }\n fragment Unused1 on Human {\n name\n ...Unused2\n }\n fragment Unused2 on Human {\n name\n ...Unused1\n }\n ", - "errors": [ - { - "message": "Fragment \"Unused1\" is never used.", - "locations": [ - { - "line": 22, - "column": 7 - } - ] - }, - { - "message": "Fragment \"Unused2\" is never used.", - "locations": [ - { - "line": 26, - "column": 7 - } - ] - } - ] - }, - { - "name": "Validate: No unused fragments/contains unknown and undef fragments", - "rule": "NoUnusedFragments", - "schema": 0, - "query": "\n query Foo {\n human(id: 4) {\n ...bar\n }\n }\n fragment foo on Human {\n name\n }\n ", - "errors": [ - { - "message": "Fragment \"foo\" is never used.", - "locations": [ - { - "line": 7, - "column": 7 - } - ] - } - ] - }, - { - "name": "Validate: No unused variables/uses all variables", - "rule": "NoUnusedVariables", - "schema": 0, - "query": "\n query ($a: String, $b: String, $c: String) {\n field(a: $a, b: $b, c: $c)\n }\n ", - "errors": [] - }, - { - "name": "Validate: No unused variables/uses all variables deeply", - "rule": "NoUnusedVariables", - "schema": 0, - "query": "\n query Foo($a: String, $b: String, $c: String) {\n field(a: $a) {\n field(b: $b) {\n field(c: $c)\n }\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: No unused variables/uses all variables deeply in inline fragments", - "rule": "NoUnusedVariables", - "schema": 0, - "query": "\n query Foo($a: String, $b: String, $c: String) {\n ... on Type {\n field(a: $a) {\n field(b: $b) {\n ... on Type {\n field(c: $c)\n }\n }\n }\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: No unused variables/uses all variables in fragments", - "rule": "NoUnusedVariables", - "schema": 0, - "query": "\n query Foo($a: String, $b: String, $c: String) {\n ...FragA\n }\n fragment FragA on Type {\n field(a: $a) {\n ...FragB\n }\n }\n fragment FragB on Type {\n field(b: $b) {\n ...FragC\n }\n }\n fragment FragC on Type {\n field(c: $c)\n }\n ", - "errors": [] - }, - { - "name": "Validate: No unused variables/variable used by fragment in multiple operations", - "rule": "NoUnusedVariables", - "schema": 0, - "query": "\n query Foo($a: String) {\n ...FragA\n }\n query Bar($b: String) {\n ...FragB\n }\n fragment FragA on Type {\n field(a: $a)\n }\n fragment FragB on Type {\n field(b: $b)\n }\n ", - "errors": [] - }, - { - "name": "Validate: No unused variables/variable used by recursive fragment", - "rule": "NoUnusedVariables", - "schema": 0, - "query": "\n query Foo($a: String) {\n ...FragA\n }\n fragment FragA on Type {\n field(a: $a) {\n ...FragA\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: No unused variables/variable not used", - "rule": "NoUnusedVariables", - "schema": 0, - "query": "\n query ($a: String, $b: String, $c: String) {\n field(a: $a, b: $b)\n }\n ", - "errors": [ - { - "message": "Variable \"$c\" is never used.", - "locations": [ - { - "line": 2, - "column": 38 - } - ] - } - ] - }, - { - "name": "Validate: No unused variables/multiple variables not used", - "rule": "NoUnusedVariables", - "schema": 0, - "query": "\n query Foo($a: String, $b: String, $c: String) {\n field(b: $b)\n }\n ", - "errors": [ - { - "message": "Variable \"$a\" is never used in operation \"Foo\".", - "locations": [ - { - "line": 2, - "column": 17 - } - ] - }, - { - "message": "Variable \"$c\" is never used in operation \"Foo\".", - "locations": [ - { - "line": 2, - "column": 41 - } - ] - } - ] - }, - { - "name": "Validate: No unused variables/variable not used in fragments", - "rule": "NoUnusedVariables", - "schema": 0, - "query": "\n query Foo($a: String, $b: String, $c: String) {\n ...FragA\n }\n fragment FragA on Type {\n field(a: $a) {\n ...FragB\n }\n }\n fragment FragB on Type {\n field(b: $b) {\n ...FragC\n }\n }\n fragment FragC on Type {\n field\n }\n ", - "errors": [ - { - "message": "Variable \"$c\" is never used in operation \"Foo\".", - "locations": [ - { - "line": 2, - "column": 41 - } - ] - } - ] - }, - { - "name": "Validate: No unused variables/multiple variables not used in fragments", - "rule": "NoUnusedVariables", - "schema": 0, - "query": "\n query Foo($a: String, $b: String, $c: String) {\n ...FragA\n }\n fragment FragA on Type {\n field {\n ...FragB\n }\n }\n fragment FragB on Type {\n field(b: $b) {\n ...FragC\n }\n }\n fragment FragC on Type {\n field\n }\n ", - "errors": [ - { - "message": "Variable \"$a\" is never used in operation \"Foo\".", - "locations": [ - { - "line": 2, - "column": 17 - } - ] - }, - { - "message": "Variable \"$c\" is never used in operation \"Foo\".", - "locations": [ - { - "line": 2, - "column": 41 - } - ] - } - ] - }, - { - "name": "Validate: No unused variables/variable not used by unreferenced fragment", - "rule": "NoUnusedVariables", - "schema": 0, - "query": "\n query Foo($b: String) {\n ...FragA\n }\n fragment FragA on Type {\n field(a: $a)\n }\n fragment FragB on Type {\n field(b: $b)\n }\n ", - "errors": [ - { - "message": "Variable \"$b\" is never used in operation \"Foo\".", - "locations": [ - { - "line": 2, - "column": 17 - } - ] - } - ] - }, - { - "name": "Validate: No unused variables/variable not used by fragment used by other operation", - "rule": "NoUnusedVariables", - "schema": 0, - "query": "\n query Foo($b: String) {\n ...FragA\n }\n query Bar($a: String) {\n ...FragB\n }\n fragment FragA on Type {\n field(a: $a)\n }\n fragment FragB on Type {\n field(b: $b)\n }\n ", - "errors": [ - { - "message": "Variable \"$b\" is never used in operation \"Foo\".", - "locations": [ - { - "line": 2, - "column": 17 - } - ] - }, - { - "message": "Variable \"$a\" is never used in operation \"Bar\".", - "locations": [ - { - "line": 5, - "column": 17 - } - ] - } - ] - }, - { - "name": "Validate: Overlapping fields can be merged/unique fields", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 0, - "query": "\n fragment uniqueFields on Dog {\n name\n nickname\n }\n ", - "errors": [] - }, - { - "name": "Validate: Overlapping fields can be merged/identical fields", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 0, - "query": "\n fragment mergeIdenticalFields on Dog {\n name\n name\n }\n ", - "errors": [] - }, - { - "name": "Validate: Overlapping fields can be merged/identical fields with identical args", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 0, - "query": "\n fragment mergeIdenticalFieldsWithIdenticalArgs on Dog {\n doesKnowCommand(dogCommand: SIT)\n doesKnowCommand(dogCommand: SIT)\n }\n ", - "errors": [] - }, - { - "name": "Validate: Overlapping fields can be merged/identical fields with identical directives", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 0, - "query": "\n fragment mergeSameFieldsWithSameDirectives on Dog {\n name @include(if: true)\n name @include(if: true)\n }\n ", - "errors": [] - }, - { - "name": "Validate: Overlapping fields can be merged/different args with different aliases", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 0, - "query": "\n fragment differentArgsWithDifferentAliases on Dog {\n knowsSit: doesKnowCommand(dogCommand: SIT)\n knowsDown: doesKnowCommand(dogCommand: DOWN)\n }\n ", - "errors": [] - }, - { - "name": "Validate: Overlapping fields can be merged/different directives with different aliases", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 0, - "query": "\n fragment differentDirectivesWithDifferentAliases on Dog {\n nameIfTrue: name @include(if: true)\n nameIfFalse: name @include(if: false)\n }\n ", - "errors": [] - }, - { - "name": "Validate: Overlapping fields can be merged/different skip/include directives accepted", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 0, - "query": "\n fragment differentDirectivesWithDifferentAliases on Dog {\n name @include(if: true)\n name @include(if: false)\n }\n ", - "errors": [] - }, - { - "name": "Validate: Overlapping fields can be merged/Same aliases with different field targets", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 0, - "query": "\n fragment sameAliasesWithDifferentFieldTargets on Dog {\n fido: name\n fido: nickname\n }\n ", - "errors": [ - { - "message": "Fields \"fido\" conflict because name and nickname are different fields. Use different aliases on the fields to fetch both if this was intentional.", - "locations": [ - { - "line": 3, - "column": 9 - }, - { - "line": 4, - "column": 9 - } - ] - } - ] - }, - { - "name": "Validate: Overlapping fields can be merged/Same aliases allowed on non-overlapping fields", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 0, - "query": "\n fragment sameAliasesWithDifferentFieldTargets on Pet {\n ... on Dog {\n name\n }\n ... on Cat {\n name: nickname\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Overlapping fields can be merged/Alias masking direct field access", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 0, - "query": "\n fragment aliasMaskingDirectFieldAccess on Dog {\n name: nickname\n name\n }\n ", - "errors": [ - { - "message": "Fields \"name\" conflict because nickname and name are different fields. Use different aliases on the fields to fetch both if this was intentional.", - "locations": [ - { - "line": 3, - "column": 9 - }, - { - "line": 4, - "column": 9 - } - ] - } - ] - }, - { - "name": "Validate: Overlapping fields can be merged/different args, second adds an argument", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 0, - "query": "\n fragment conflictingArgs on Dog {\n doesKnowCommand\n doesKnowCommand(dogCommand: HEEL)\n }\n ", - "errors": [ - { - "message": "Fields \"doesKnowCommand\" conflict because they have differing arguments. Use different aliases on the fields to fetch both if this was intentional.", - "locations": [ - { - "line": 3, - "column": 9 - }, - { - "line": 4, - "column": 9 - } - ] - } - ] - }, - { - "name": "Validate: Overlapping fields can be merged/different args, second missing an argument", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 0, - "query": "\n fragment conflictingArgs on Dog {\n doesKnowCommand(dogCommand: SIT)\n doesKnowCommand\n }\n ", - "errors": [ - { - "message": "Fields \"doesKnowCommand\" conflict because they have differing arguments. Use different aliases on the fields to fetch both if this was intentional.", - "locations": [ - { - "line": 3, - "column": 9 - }, - { - "line": 4, - "column": 9 - } - ] - } - ] - }, - { - "name": "Validate: Overlapping fields can be merged/conflicting args", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 0, - "query": "\n fragment conflictingArgs on Dog {\n doesKnowCommand(dogCommand: SIT)\n doesKnowCommand(dogCommand: HEEL)\n }\n ", - "errors": [ - { - "message": "Fields \"doesKnowCommand\" conflict because they have differing arguments. Use different aliases on the fields to fetch both if this was intentional.", - "locations": [ - { - "line": 3, - "column": 9 - }, - { - "line": 4, - "column": 9 - } - ] - } - ] - }, - { - "name": "Validate: Overlapping fields can be merged/allows different args where no conflict is possible", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 0, - "query": "\n fragment conflictingArgs on Pet {\n ... on Dog {\n name(surname: true)\n }\n ... on Cat {\n name\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Overlapping fields can be merged/encounters conflict in fragments", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 0, - "query": "\n {\n ...A\n ...B\n }\n fragment A on Type {\n x: a\n }\n fragment B on Type {\n x: b\n }\n ", - "errors": [ - { - "message": "Fields \"x\" conflict because a and b are different fields. Use different aliases on the fields to fetch both if this was intentional.", - "locations": [ - { - "line": 7, - "column": 9 - }, - { - "line": 10, - "column": 9 - } - ] - } - ] - }, - { - "name": "Validate: Overlapping fields can be merged/reports each conflict once", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 0, - "query": "\n {\n f1 {\n ...A\n ...B\n }\n f2 {\n ...B\n ...A\n }\n f3 {\n ...A\n ...B\n x: c\n }\n }\n fragment A on Type {\n x: a\n }\n fragment B on Type {\n x: b\n }\n ", - "errors": [ - { - "message": "Fields \"x\" conflict because a and b are different fields. Use different aliases on the fields to fetch both if this was intentional.", - "locations": [ - { - "line": 18, - "column": 9 - }, - { - "line": 21, - "column": 9 - } - ] - }, - { - "message": "Fields \"x\" conflict because c and a are different fields. Use different aliases on the fields to fetch both if this was intentional.", - "locations": [ - { - "line": 14, - "column": 11 - }, - { - "line": 18, - "column": 9 - } - ] - }, - { - "message": "Fields \"x\" conflict because c and b are different fields. Use different aliases on the fields to fetch both if this was intentional.", - "locations": [ - { - "line": 14, - "column": 11 - }, - { - "line": 21, - "column": 9 - } - ] - } - ] - }, - { - "name": "Validate: Overlapping fields can be merged/deep conflict", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 0, - "query": "\n {\n field {\n x: a\n },\n field {\n x: b\n }\n }\n ", - "errors": [ - { - "message": "Fields \"field\" conflict because subfields \"x\" conflict because a and b are different fields. Use different aliases on the fields to fetch both if this was intentional.", - "locations": [ - { - "line": 3, - "column": 9 - }, - { - "line": 4, - "column": 11 - }, - { - "line": 6, - "column": 9 - }, - { - "line": 7, - "column": 11 - } - ] - } - ] - }, - { - "name": "Validate: Overlapping fields can be merged/deep conflict with multiple issues", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 0, - "query": "\n {\n field {\n x: a\n y: c\n },\n field {\n x: b\n y: d\n }\n }\n ", - "errors": [ - { - "message": "Fields \"field\" conflict because subfields \"x\" conflict because a and b are different fields and subfields \"y\" conflict because c and d are different fields. Use different aliases on the fields to fetch both if this was intentional.", - "locations": [ - { - "line": 3, - "column": 9 - }, - { - "line": 4, - "column": 11 - }, - { - "line": 5, - "column": 11 - }, - { - "line": 7, - "column": 9 - }, - { - "line": 8, - "column": 11 - }, - { - "line": 9, - "column": 11 - } - ] - } - ] - }, - { - "name": "Validate: Overlapping fields can be merged/very deep conflict", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 0, - "query": "\n {\n field {\n deepField {\n x: a\n }\n },\n field {\n deepField {\n x: b\n }\n }\n }\n ", - "errors": [ - { - "message": "Fields \"field\" conflict because subfields \"deepField\" conflict because subfields \"x\" conflict because a and b are different fields. Use different aliases on the fields to fetch both if this was intentional.", - "locations": [ - { - "line": 3, - "column": 9 - }, - { - "line": 4, - "column": 11 - }, - { - "line": 5, - "column": 13 - }, - { - "line": 8, - "column": 9 - }, - { - "line": 9, - "column": 11 - }, - { - "line": 10, - "column": 13 - } - ] - } - ] - }, - { - "name": "Validate: Overlapping fields can be merged/reports deep conflict to nearest common ancestor", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 0, - "query": "\n {\n field {\n deepField {\n x: a\n }\n deepField {\n x: b\n }\n },\n field {\n deepField {\n y\n }\n }\n }\n ", - "errors": [ - { - "message": "Fields \"deepField\" conflict because subfields \"x\" conflict because a and b are different fields. Use different aliases on the fields to fetch both if this was intentional.", - "locations": [ - { - "line": 4, - "column": 11 - }, - { - "line": 5, - "column": 13 - }, - { - "line": 7, - "column": 11 - }, - { - "line": 8, - "column": 13 - } - ] - } - ] - }, - { - "name": "Validate: Overlapping fields can be merged/reports deep conflict to nearest common ancestor in fragments", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 0, - "query": "\n {\n field {\n ...F\n }\n field {\n ...F\n }\n }\n fragment F on T {\n deepField {\n deeperField {\n x: a\n }\n deeperField {\n x: b\n }\n },\n deepField {\n deeperField {\n y\n }\n }\n }\n ", - "errors": [ - { - "message": "Fields \"deeperField\" conflict because subfields \"x\" conflict because a and b are different fields. Use different aliases on the fields to fetch both if this was intentional.", - "locations": [ - { - "line": 12, - "column": 11 - }, - { - "line": 13, - "column": 13 - }, - { - "line": 15, - "column": 11 - }, - { - "line": 16, - "column": 13 - } - ] - } - ] - }, - { - "name": "Validate: Overlapping fields can be merged/reports deep conflict in nested fragments", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 0, - "query": "\n {\n field {\n ...F\n }\n field {\n ...I\n }\n }\n fragment F on T {\n x: a\n ...G\n }\n fragment G on T {\n y: c\n }\n fragment I on T {\n y: d\n ...J\n }\n fragment J on T {\n x: b\n }\n ", - "errors": [ - { - "message": "Fields \"field\" conflict because subfields \"x\" conflict because a and b are different fields and subfields \"y\" conflict because c and d are different fields. Use different aliases on the fields to fetch both if this was intentional.", - "locations": [ - { - "line": 3, - "column": 9 - }, - { - "line": 11, - "column": 9 - }, - { - "line": 15, - "column": 9 - }, - { - "line": 6, - "column": 9 - }, - { - "line": 22, - "column": 9 - }, - { - "line": 18, - "column": 9 - } - ] - } - ] - }, - { - "name": "Validate: Overlapping fields can be merged/ignores unknown fragments", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 0, - "query": "\n {\n field\n ...Unknown\n ...Known\n }\n\n fragment Known on T {\n field\n ...OtherUnknown\n }\n ", - "errors": [] - }, - { - "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/conflicting return types which potentially overlap", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 1, - "query": "\n {\n someBox {\n ...on IntBox {\n scalar\n }\n ...on NonNullStringBox1 {\n scalar\n }\n }\n }\n ", - "errors": [ - { - "message": "Fields \"scalar\" conflict because they return conflicting types Int and String!. Use different aliases on the fields to fetch both if this was intentional.", - "locations": [ - { - "line": 5, - "column": 15 - }, - { - "line": 8, - "column": 15 - } - ] - } - ] - }, - { - "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/compatible return shapes on different return types", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 1, - "query": "\n {\n someBox {\n ... on SomeBox {\n deepBox {\n unrelatedField\n }\n }\n ... on StringBox {\n deepBox {\n unrelatedField\n }\n }\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/disallows differing return types despite no overlap", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 1, - "query": "\n {\n someBox {\n ... on IntBox {\n scalar\n }\n ... on StringBox {\n scalar\n }\n }\n }\n ", - "errors": [ - { - "message": "Fields \"scalar\" conflict because they return conflicting types Int and String. Use different aliases on the fields to fetch both if this was intentional.", - "locations": [ - { - "line": 5, - "column": 15 - }, - { - "line": 8, - "column": 15 - } - ] - } - ] - }, - { - "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/disallows differing return type nullability despite no overlap", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 1, - "query": "\n {\n someBox {\n ... on NonNullStringBox1 {\n scalar\n }\n ... on StringBox {\n scalar\n }\n }\n }\n ", - "errors": [ - { - "message": "Fields \"scalar\" conflict because they return conflicting types String! and String. Use different aliases on the fields to fetch both if this was intentional.", - "locations": [ - { - "line": 5, - "column": 15 - }, - { - "line": 8, - "column": 15 - } - ] - } - ] - }, - { - "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/disallows differing return type list despite no overlap", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 1, - "query": "\n {\n someBox {\n ... on IntBox {\n box: listStringBox {\n scalar\n }\n }\n ... on StringBox {\n box: stringBox {\n scalar\n }\n }\n }\n }\n ", - "errors": [ - { - "message": "Fields \"box\" conflict because they return conflicting types [StringBox] and StringBox. Use different aliases on the fields to fetch both if this was intentional.", - "locations": [ - { - "line": 5, - "column": 15 - }, - { - "line": 10, - "column": 15 - } - ] - } - ] - }, - { - "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/disallows differing return type list despite no overlap", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 1, - "query": "\n {\n someBox {\n ... on IntBox {\n box: stringBox {\n scalar\n }\n }\n ... on StringBox {\n box: listStringBox {\n scalar\n }\n }\n }\n }\n ", - "errors": [ - { - "message": "Fields \"box\" conflict because they return conflicting types StringBox and [StringBox]. Use different aliases on the fields to fetch both if this was intentional.", - "locations": [ - { - "line": 5, - "column": 15 - }, - { - "line": 10, - "column": 15 - } - ] - } - ] - }, - { - "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/disallows differing deep return types despite no overlap", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 1, - "query": "\n {\n someBox {\n ... on IntBox {\n box: stringBox {\n scalar\n }\n }\n ... on StringBox {\n box: intBox {\n scalar\n }\n }\n }\n }\n ", - "errors": [ - { - "message": "Fields \"box\" conflict because subfields \"scalar\" conflict because they return conflicting types String and Int. Use different aliases on the fields to fetch both if this was intentional.", - "locations": [ - { - "line": 5, - "column": 15 - }, - { - "line": 6, - "column": 17 - }, - { - "line": 10, - "column": 15 - }, - { - "line": 11, - "column": 17 - } - ] - } - ] - }, - { - "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/allows non-conflicting overlaping types", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 1, - "query": "\n {\n someBox {\n ... on IntBox {\n scalar: unrelatedField\n }\n ... on StringBox {\n scalar\n }\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/same wrapped scalar return types", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 1, - "query": "\n {\n someBox {\n ...on NonNullStringBox1 {\n scalar\n }\n ...on NonNullStringBox2 {\n scalar\n }\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/allows inline typeless fragments", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 1, - "query": "\n {\n a\n ... {\n a\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/compares deep types including list", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 1, - "query": "\n {\n connection {\n ...edgeID\n edges {\n node {\n id: name\n }\n }\n }\n }\n\n fragment edgeID on Connection {\n edges {\n node {\n id\n }\n }\n }\n ", - "errors": [ - { - "message": "Fields \"edges\" conflict because subfields \"node\" conflict because subfields \"id\" conflict because name and id are different fields. Use different aliases on the fields to fetch both if this was intentional.", - "locations": [ - { - "line": 5, - "column": 13 - }, - { - "line": 6, - "column": 15 - }, - { - "line": 7, - "column": 17 - }, - { - "line": 14, - "column": 11 - }, - { - "line": 15, - "column": 13 - }, - { - "line": 16, - "column": 15 - } - ] - } - ] - }, - { - "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/ignores unknown types", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 1, - "query": "\n {\n someBox {\n ...on UnknownType {\n scalar\n }\n ...on NonNullStringBox2 {\n scalar\n }\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/works for field names that are JS keywords", - "rule": "OverlappingFieldsCanBeMerged", - "schema": 2, - "query": "{\n foo {\n constructor\n }\n }", - "errors": [] - }, - { - "name": "Validate: Possible fragment spreads/of the same object", - "rule": "PossibleFragmentSpreads", - "schema": 0, - "query": "\n fragment objectWithinObject on Dog { ...dogFragment }\n fragment dogFragment on Dog { barkVolume }\n ", - "errors": [] - }, - { - "name": "Validate: Possible fragment spreads/of the same object with inline fragment", - "rule": "PossibleFragmentSpreads", - "schema": 0, - "query": "\n fragment objectWithinObjectAnon on Dog { ... on Dog { barkVolume } }\n ", - "errors": [] - }, - { - "name": "Validate: Possible fragment spreads/object into an implemented interface", - "rule": "PossibleFragmentSpreads", - "schema": 0, - "query": "\n fragment objectWithinInterface on Pet { ...dogFragment }\n fragment dogFragment on Dog { barkVolume }\n ", - "errors": [] - }, - { - "name": "Validate: Possible fragment spreads/object into containing union", - "rule": "PossibleFragmentSpreads", - "schema": 0, - "query": "\n fragment objectWithinUnion on CatOrDog { ...dogFragment }\n fragment dogFragment on Dog { barkVolume }\n ", - "errors": [] - }, - { - "name": "Validate: Possible fragment spreads/union into contained object", - "rule": "PossibleFragmentSpreads", - "schema": 0, - "query": "\n fragment unionWithinObject on Dog { ...catOrDogFragment }\n fragment catOrDogFragment on CatOrDog { __typename }\n ", - "errors": [] - }, - { - "name": "Validate: Possible fragment spreads/union into overlapping interface", - "rule": "PossibleFragmentSpreads", - "schema": 0, - "query": "\n fragment unionWithinInterface on Pet { ...catOrDogFragment }\n fragment catOrDogFragment on CatOrDog { __typename }\n ", - "errors": [] - }, - { - "name": "Validate: Possible fragment spreads/union into overlapping union", - "rule": "PossibleFragmentSpreads", - "schema": 0, - "query": "\n fragment unionWithinUnion on DogOrHuman { ...catOrDogFragment }\n fragment catOrDogFragment on CatOrDog { __typename }\n ", - "errors": [] - }, - { - "name": "Validate: Possible fragment spreads/interface into implemented object", - "rule": "PossibleFragmentSpreads", - "schema": 0, - "query": "\n fragment interfaceWithinObject on Dog { ...petFragment }\n fragment petFragment on Pet { name }\n ", - "errors": [] - }, - { - "name": "Validate: Possible fragment spreads/interface into overlapping interface", - "rule": "PossibleFragmentSpreads", - "schema": 0, - "query": "\n fragment interfaceWithinInterface on Pet { ...beingFragment }\n fragment beingFragment on Being { name }\n ", - "errors": [] - }, - { - "name": "Validate: Possible fragment spreads/interface into overlapping interface in inline fragment", - "rule": "PossibleFragmentSpreads", - "schema": 0, - "query": "\n fragment interfaceWithinInterface on Pet { ... on Being { name } }\n ", - "errors": [] - }, - { - "name": "Validate: Possible fragment spreads/interface into overlapping union", - "rule": "PossibleFragmentSpreads", - "schema": 0, - "query": "\n fragment interfaceWithinUnion on CatOrDog { ...petFragment }\n fragment petFragment on Pet { name }\n ", - "errors": [] - }, - { - "name": "Validate: Possible fragment spreads/different object into object", - "rule": "PossibleFragmentSpreads", - "schema": 0, - "query": "\n fragment invalidObjectWithinObject on Cat { ...dogFragment }\n fragment dogFragment on Dog { barkVolume }\n ", - "errors": [ - { - "message": "Fragment \"dogFragment\" cannot be spread here as objects of type \"Cat\" can never be of type \"Dog\".", - "locations": [ - { - "line": 2, - "column": 51 - } - ] - } - ] - }, - { - "name": "Validate: Possible fragment spreads/different object into object in inline fragment", - "rule": "PossibleFragmentSpreads", - "schema": 0, - "query": "\n fragment invalidObjectWithinObjectAnon on Cat {\n ... on Dog { barkVolume }\n }\n ", - "errors": [ - { - "message": "Fragment cannot be spread here as objects of type \"Cat\" can never be of type \"Dog\".", - "locations": [ - { - "line": 3, - "column": 9 - } - ] - } - ] - }, - { - "name": "Validate: Possible fragment spreads/object into not implementing interface", - "rule": "PossibleFragmentSpreads", - "schema": 0, - "query": "\n fragment invalidObjectWithinInterface on Pet { ...humanFragment }\n fragment humanFragment on Human { pets { name } }\n ", - "errors": [ - { - "message": "Fragment \"humanFragment\" cannot be spread here as objects of type \"Pet\" can never be of type \"Human\".", - "locations": [ - { - "line": 2, - "column": 54 - } - ] - } - ] - }, - { - "name": "Validate: Possible fragment spreads/object into not containing union", - "rule": "PossibleFragmentSpreads", - "schema": 0, - "query": "\n fragment invalidObjectWithinUnion on CatOrDog { ...humanFragment }\n fragment humanFragment on Human { pets { name } }\n ", - "errors": [ - { - "message": "Fragment \"humanFragment\" cannot be spread here as objects of type \"CatOrDog\" can never be of type \"Human\".", - "locations": [ - { - "line": 2, - "column": 55 - } - ] - } - ] - }, - { - "name": "Validate: Possible fragment spreads/union into not contained object", - "rule": "PossibleFragmentSpreads", - "schema": 0, - "query": "\n fragment invalidUnionWithinObject on Human { ...catOrDogFragment }\n fragment catOrDogFragment on CatOrDog { __typename }\n ", - "errors": [ - { - "message": "Fragment \"catOrDogFragment\" cannot be spread here as objects of type \"Human\" can never be of type \"CatOrDog\".", - "locations": [ - { - "line": 2, - "column": 52 - } - ] - } - ] - }, - { - "name": "Validate: Possible fragment spreads/union into non overlapping interface", - "rule": "PossibleFragmentSpreads", - "schema": 0, - "query": "\n fragment invalidUnionWithinInterface on Pet { ...humanOrAlienFragment }\n fragment humanOrAlienFragment on HumanOrAlien { __typename }\n ", - "errors": [ - { - "message": "Fragment \"humanOrAlienFragment\" cannot be spread here as objects of type \"Pet\" can never be of type \"HumanOrAlien\".", - "locations": [ - { - "line": 2, - "column": 53 - } - ] - } - ] - }, - { - "name": "Validate: Possible fragment spreads/union into non overlapping union", - "rule": "PossibleFragmentSpreads", - "schema": 0, - "query": "\n fragment invalidUnionWithinUnion on CatOrDog { ...humanOrAlienFragment }\n fragment humanOrAlienFragment on HumanOrAlien { __typename }\n ", - "errors": [ - { - "message": "Fragment \"humanOrAlienFragment\" cannot be spread here as objects of type \"CatOrDog\" can never be of type \"HumanOrAlien\".", - "locations": [ - { - "line": 2, - "column": 54 - } - ] - } - ] - }, - { - "name": "Validate: Possible fragment spreads/interface into non implementing object", - "rule": "PossibleFragmentSpreads", - "schema": 0, - "query": "\n fragment invalidInterfaceWithinObject on Cat { ...intelligentFragment }\n fragment intelligentFragment on Intelligent { iq }\n ", - "errors": [ - { - "message": "Fragment \"intelligentFragment\" cannot be spread here as objects of type \"Cat\" can never be of type \"Intelligent\".", - "locations": [ - { - "line": 2, - "column": 54 - } - ] - } - ] - }, - { - "name": "Validate: Possible fragment spreads/interface into non overlapping interface", - "rule": "PossibleFragmentSpreads", - "schema": 0, - "query": "\n fragment invalidInterfaceWithinInterface on Pet {\n ...intelligentFragment\n }\n fragment intelligentFragment on Intelligent { iq }\n ", - "errors": [ - { - "message": "Fragment \"intelligentFragment\" cannot be spread here as objects of type \"Pet\" can never be of type \"Intelligent\".", - "locations": [ - { - "line": 3, - "column": 9 - } - ] - } - ] - }, - { - "name": "Validate: Possible fragment spreads/interface into non overlapping interface in inline fragment", - "rule": "PossibleFragmentSpreads", - "schema": 0, - "query": "\n fragment invalidInterfaceWithinInterfaceAnon on Pet {\n ...on Intelligent { iq }\n }\n ", - "errors": [ - { - "message": "Fragment cannot be spread here as objects of type \"Pet\" can never be of type \"Intelligent\".", - "locations": [ - { - "line": 3, - "column": 9 - } - ] - } - ] - }, - { - "name": "Validate: Possible fragment spreads/interface into non overlapping union", - "rule": "PossibleFragmentSpreads", - "schema": 0, - "query": "\n fragment invalidInterfaceWithinUnion on HumanOrAlien { ...petFragment }\n fragment petFragment on Pet { name }\n ", - "errors": [ - { - "message": "Fragment \"petFragment\" cannot be spread here as objects of type \"HumanOrAlien\" can never be of type \"Pet\".", - "locations": [ - { - "line": 2, - "column": 62 - } - ] - } - ] - }, - { - "name": "Validate: Provided required arguments/ignores unknown arguments", - "rule": "ProvidedNonNullArguments", - "schema": 0, - "query": "\n {\n dog {\n isHousetrained(unknownArgument: true)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Provided required arguments/Valid non-nullable value/Arg on optional arg", - "rule": "ProvidedNonNullArguments", - "schema": 0, - "query": "\n {\n dog {\n isHousetrained(atOtherHomes: true)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Provided required arguments/Valid non-nullable value/No Arg on optional arg", - "rule": "ProvidedNonNullArguments", - "schema": 0, - "query": "\n {\n dog {\n isHousetrained\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Provided required arguments/Valid non-nullable value/Multiple args", - "rule": "ProvidedNonNullArguments", - "schema": 0, - "query": "\n {\n complicatedArgs {\n multipleReqs(req1: 1, req2: 2)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Provided required arguments/Valid non-nullable value/Multiple args reverse order", - "rule": "ProvidedNonNullArguments", - "schema": 0, - "query": "\n {\n complicatedArgs {\n multipleReqs(req2: 2, req1: 1)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Provided required arguments/Valid non-nullable value/No args on multiple optional", - "rule": "ProvidedNonNullArguments", - "schema": 0, - "query": "\n {\n complicatedArgs {\n multipleOpts\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Provided required arguments/Valid non-nullable value/One arg on multiple optional", - "rule": "ProvidedNonNullArguments", - "schema": 0, - "query": "\n {\n complicatedArgs {\n multipleOpts(opt1: 1)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Provided required arguments/Valid non-nullable value/Second arg on multiple optional", - "rule": "ProvidedNonNullArguments", - "schema": 0, - "query": "\n {\n complicatedArgs {\n multipleOpts(opt2: 1)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Provided required arguments/Valid non-nullable value/Multiple reqs on mixedList", - "rule": "ProvidedNonNullArguments", - "schema": 0, - "query": "\n {\n complicatedArgs {\n multipleOptAndReq(req1: 3, req2: 4)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Provided required arguments/Valid non-nullable value/Multiple reqs and one opt on mixedList", - "rule": "ProvidedNonNullArguments", - "schema": 0, - "query": "\n {\n complicatedArgs {\n multipleOptAndReq(req1: 3, req2: 4, opt1: 5)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Provided required arguments/Valid non-nullable value/All reqs and opts on mixedList", - "rule": "ProvidedNonNullArguments", - "schema": 0, - "query": "\n {\n complicatedArgs {\n multipleOptAndReq(req1: 3, req2: 4, opt1: 5, opt2: 6)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Provided required arguments/Invalid non-nullable value/Missing one non-nullable argument", - "rule": "ProvidedNonNullArguments", - "schema": 0, - "query": "\n {\n complicatedArgs {\n multipleReqs(req2: 2)\n }\n }\n ", - "errors": [ - { - "message": "Field \"multipleReqs\" argument \"req1\" of type \"Int!\" is required but not provided.", - "locations": [ - { - "line": 4, - "column": 13 - } - ] - } - ] - }, - { - "name": "Validate: Provided required arguments/Invalid non-nullable value/Missing multiple non-nullable arguments", - "rule": "ProvidedNonNullArguments", - "schema": 0, - "query": "\n {\n complicatedArgs {\n multipleReqs\n }\n }\n ", - "errors": [ - { - "message": "Field \"multipleReqs\" argument \"req1\" of type \"Int!\" is required but not provided.", - "locations": [ - { - "line": 4, - "column": 13 - } - ] - }, - { - "message": "Field \"multipleReqs\" argument \"req2\" of type \"Int!\" is required but not provided.", - "locations": [ - { - "line": 4, - "column": 13 - } - ] - } - ] - }, - { - "name": "Validate: Provided required arguments/Invalid non-nullable value/Incorrect value and missing argument", - "rule": "ProvidedNonNullArguments", - "schema": 0, - "query": "\n {\n complicatedArgs {\n multipleReqs(req1: \"one\")\n }\n }\n ", - "errors": [ - { - "message": "Field \"multipleReqs\" argument \"req2\" of type \"Int!\" is required but not provided.", - "locations": [ - { - "line": 4, - "column": 13 - } - ] - } - ] - }, - { - "name": "Validate: Provided required arguments/Directive arguments/ignores unknown directives", - "rule": "ProvidedNonNullArguments", - "schema": 0, - "query": "\n {\n dog @unknown\n }\n ", - "errors": [] - }, - { - "name": "Validate: Provided required arguments/Directive arguments/with directives of valid types", - "rule": "ProvidedNonNullArguments", - "schema": 0, - "query": "\n {\n dog @include(if: true) {\n name\n }\n human @skip(if: false) {\n name\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Provided required arguments/Directive arguments/with directive with missing types", - "rule": "ProvidedNonNullArguments", - "schema": 0, - "query": "\n {\n dog @include {\n name @skip\n }\n }\n ", - "errors": [ - { - "message": "Directive \"@include\" argument \"if\" of type \"Boolean!\" is required but not provided.", - "locations": [ - { - "line": 3, - "column": 15 - } - ] - }, - { - "message": "Directive \"@skip\" argument \"if\" of type \"Boolean!\" is required but not provided.", - "locations": [ - { - "line": 4, - "column": 18 - } - ] - } - ] - }, - { - "name": "Validate: Scalar leafs/valid scalar selection", - "rule": "ScalarLeafs", - "schema": 0, - "query": "\n fragment scalarSelection on Dog {\n barks\n }\n ", - "errors": [] - }, - { - "name": "Validate: Scalar leafs/object type missing selection", - "rule": "ScalarLeafs", - "schema": 0, - "query": "\n query directQueryOnObjectWithoutSubFields {\n human\n }\n ", - "errors": [ - { - "message": "Field \"human\" of type \"Human\" must have a selection of subfields. Did you mean \"human { ... }\"?", - "locations": [ - { - "line": 3, - "column": 9 - } - ] - } - ] - }, - { - "name": "Validate: Scalar leafs/interface type missing selection", - "rule": "ScalarLeafs", - "schema": 0, - "query": "\n {\n human { pets }\n }\n ", - "errors": [ - { - "message": "Field \"pets\" of type \"[Pet]\" must have a selection of subfields. Did you mean \"pets { ... }\"?", - "locations": [ - { - "line": 3, - "column": 17 - } - ] - } - ] - }, - { - "name": "Validate: Scalar leafs/valid scalar selection with args", - "rule": "ScalarLeafs", - "schema": 0, - "query": "\n fragment scalarSelectionWithArgs on Dog {\n doesKnowCommand(dogCommand: SIT)\n }\n ", - "errors": [] - }, - { - "name": "Validate: Scalar leafs/scalar selection not allowed on Boolean", - "rule": "ScalarLeafs", - "schema": 0, - "query": "\n fragment scalarSelectionsNotAllowedOnBoolean on Dog {\n barks { sinceWhen }\n }\n ", - "errors": [ - { - "message": "Field \"barks\" must not have a selection since type \"Boolean\" has no subfields.", - "locations": [ - { - "line": 3, - "column": 15 - } - ] - } - ] - }, - { - "name": "Validate: Scalar leafs/scalar selection not allowed on Enum", - "rule": "ScalarLeafs", - "schema": 0, - "query": "\n fragment scalarSelectionsNotAllowedOnEnum on Cat {\n furColor { inHexdec }\n }\n ", - "errors": [ - { - "message": "Field \"furColor\" must not have a selection since type \"FurColor\" has no subfields.", - "locations": [ - { - "line": 3, - "column": 18 - } - ] - } - ] - }, - { - "name": "Validate: Scalar leafs/scalar selection not allowed with args", - "rule": "ScalarLeafs", - "schema": 0, - "query": "\n fragment scalarSelectionsNotAllowedWithArgs on Dog {\n doesKnowCommand(dogCommand: SIT) { sinceWhen }\n }\n ", - "errors": [ - { - "message": "Field \"doesKnowCommand\" must not have a selection since type \"Boolean\" has no subfields.", - "locations": [ - { - "line": 3, - "column": 42 - } - ] - } - ] - }, - { - "name": "Validate: Scalar leafs/Scalar selection not allowed with directives", - "rule": "ScalarLeafs", - "schema": 0, - "query": "\n fragment scalarSelectionsNotAllowedWithDirectives on Dog {\n name @include(if: true) { isAlsoHumanName }\n }\n ", - "errors": [ - { - "message": "Field \"name\" must not have a selection since type \"String\" has no subfields.", - "locations": [ - { - "line": 3, - "column": 33 - } - ] - } - ] - }, - { - "name": "Validate: Scalar leafs/Scalar selection not allowed with directives and args", - "rule": "ScalarLeafs", - "schema": 0, - "query": "\n fragment scalarSelectionsNotAllowedWithDirectivesAndArgs on Dog {\n doesKnowCommand(dogCommand: SIT) @include(if: true) { sinceWhen }\n }\n ", - "errors": [ - { - "message": "Field \"doesKnowCommand\" must not have a selection since type \"Boolean\" has no subfields.", - "locations": [ - { - "line": 3, - "column": 61 - } - ] - } - ] - }, - { - "name": "Validate: Unique argument names/no arguments on field", - "rule": "UniqueArgumentNames", - "schema": 0, - "query": "\n {\n field\n }\n ", - "errors": [] - }, - { - "name": "Validate: Unique argument names/no arguments on directive", - "rule": "UniqueArgumentNames", - "schema": 0, - "query": "\n {\n field @directive\n }\n ", - "errors": [] - }, - { - "name": "Validate: Unique argument names/argument on field", - "rule": "UniqueArgumentNames", - "schema": 0, - "query": "\n {\n field(arg: \"value\")\n }\n ", - "errors": [] - }, - { - "name": "Validate: Unique argument names/argument on directive", - "rule": "UniqueArgumentNames", - "schema": 0, - "query": "\n {\n field @directive(arg: \"value\")\n }\n ", - "errors": [] - }, - { - "name": "Validate: Unique argument names/same argument on two fields", - "rule": "UniqueArgumentNames", - "schema": 0, - "query": "\n {\n one: field(arg: \"value\")\n two: field(arg: \"value\")\n }\n ", - "errors": [] - }, - { - "name": "Validate: Unique argument names/same argument on field and directive", - "rule": "UniqueArgumentNames", - "schema": 0, - "query": "\n {\n field(arg: \"value\") @directive(arg: \"value\")\n }\n ", - "errors": [] - }, - { - "name": "Validate: Unique argument names/same argument on two directives", - "rule": "UniqueArgumentNames", - "schema": 0, - "query": "\n {\n field @directive1(arg: \"value\") @directive2(arg: \"value\")\n }\n ", - "errors": [] - }, - { - "name": "Validate: Unique argument names/multiple field arguments", - "rule": "UniqueArgumentNames", - "schema": 0, - "query": "\n {\n field(arg1: \"value\", arg2: \"value\", arg3: \"value\")\n }\n ", - "errors": [] - }, - { - "name": "Validate: Unique argument names/multiple directive arguments", - "rule": "UniqueArgumentNames", - "schema": 0, - "query": "\n {\n field @directive(arg1: \"value\", arg2: \"value\", arg3: \"value\")\n }\n ", - "errors": [] - }, - { - "name": "Validate: Unique argument names/duplicate field arguments", - "rule": "UniqueArgumentNames", - "schema": 0, - "query": "\n {\n field(arg1: \"value\", arg1: \"value\")\n }\n ", - "errors": [ - { - "message": "There can be only one argument named \"arg1\".", - "locations": [ - { - "line": 3, - "column": 15 - }, - { - "line": 3, - "column": 30 - } - ] - } - ] - }, - { - "name": "Validate: Unique argument names/many duplicate field arguments", - "rule": "UniqueArgumentNames", - "schema": 0, - "query": "\n {\n field(arg1: \"value\", arg1: \"value\", arg1: \"value\")\n }\n ", - "errors": [ - { - "message": "There can be only one argument named \"arg1\".", - "locations": [ - { - "line": 3, - "column": 15 - }, - { - "line": 3, - "column": 30 - } - ] - }, - { - "message": "There can be only one argument named \"arg1\".", - "locations": [ - { - "line": 3, - "column": 15 - }, - { - "line": 3, - "column": 45 - } - ] - } - ] - }, - { - "name": "Validate: Unique argument names/duplicate directive arguments", - "rule": "UniqueArgumentNames", - "schema": 0, - "query": "\n {\n field @directive(arg1: \"value\", arg1: \"value\")\n }\n ", - "errors": [ - { - "message": "There can be only one argument named \"arg1\".", - "locations": [ - { - "line": 3, - "column": 26 - }, - { - "line": 3, - "column": 41 - } - ] - } - ] - }, - { - "name": "Validate: Unique argument names/many duplicate directive arguments", - "rule": "UniqueArgumentNames", - "schema": 0, - "query": "\n {\n field @directive(arg1: \"value\", arg1: \"value\", arg1: \"value\")\n }\n ", - "errors": [ - { - "message": "There can be only one argument named \"arg1\".", - "locations": [ - { - "line": 3, - "column": 26 - }, - { - "line": 3, - "column": 41 - } - ] - }, - { - "message": "There can be only one argument named \"arg1\".", - "locations": [ - { - "line": 3, - "column": 26 - }, - { - "line": 3, - "column": 56 - } - ] - } - ] - }, - { - "name": "Validate: Directives Are Unique Per Location/no directives", - "rule": "UniqueDirectivesPerLocation", - "schema": 0, - "query": "\n fragment Test on Type {\n field\n }\n ", - "errors": [] - }, - { - "name": "Validate: Directives Are Unique Per Location/unique directives in different locations", - "rule": "UniqueDirectivesPerLocation", - "schema": 0, - "query": "\n fragment Test on Type @directiveA {\n field @directiveB\n }\n ", - "errors": [] - }, - { - "name": "Validate: Directives Are Unique Per Location/unique directives in same locations", - "rule": "UniqueDirectivesPerLocation", - "schema": 0, - "query": "\n fragment Test on Type @directiveA @directiveB {\n field @directiveA @directiveB\n }\n ", - "errors": [] - }, - { - "name": "Validate: Directives Are Unique Per Location/same directives in different locations", - "rule": "UniqueDirectivesPerLocation", - "schema": 0, - "query": "\n fragment Test on Type @directiveA {\n field @directiveA\n }\n ", - "errors": [] - }, - { - "name": "Validate: Directives Are Unique Per Location/same directives in similar locations", - "rule": "UniqueDirectivesPerLocation", - "schema": 0, - "query": "\n fragment Test on Type {\n field @directive\n field @directive\n }\n ", - "errors": [] - }, - { - "name": "Validate: Directives Are Unique Per Location/duplicate directives in one location", - "rule": "UniqueDirectivesPerLocation", - "schema": 0, - "query": "\n fragment Test on Type {\n field @directive @directive\n }\n ", - "errors": [ - { - "message": "The directive \"directive\" can only be used once at this location.", - "locations": [ - { - "line": 3, - "column": 15 - }, - { - "line": 3, - "column": 26 - } - ] - } - ] - }, - { - "name": "Validate: Directives Are Unique Per Location/many duplicate directives in one location", - "rule": "UniqueDirectivesPerLocation", - "schema": 0, - "query": "\n fragment Test on Type {\n field @directive @directive @directive\n }\n ", - "errors": [ - { - "message": "The directive \"directive\" can only be used once at this location.", - "locations": [ - { - "line": 3, - "column": 15 - }, - { - "line": 3, - "column": 26 - } - ] - }, - { - "message": "The directive \"directive\" can only be used once at this location.", - "locations": [ - { - "line": 3, - "column": 15 - }, - { - "line": 3, - "column": 37 - } - ] - } - ] - }, - { - "name": "Validate: Directives Are Unique Per Location/different duplicate directives in one location", - "rule": "UniqueDirectivesPerLocation", - "schema": 0, - "query": "\n fragment Test on Type {\n field @directiveA @directiveB @directiveA @directiveB\n }\n ", - "errors": [ - { - "message": "The directive \"directiveA\" can only be used once at this location.", - "locations": [ - { - "line": 3, - "column": 15 - }, - { - "line": 3, - "column": 39 - } - ] - }, - { - "message": "The directive \"directiveB\" can only be used once at this location.", - "locations": [ - { - "line": 3, - "column": 27 - }, - { - "line": 3, - "column": 51 - } - ] - } - ] - }, - { - "name": "Validate: Directives Are Unique Per Location/duplicate directives in many locations", - "rule": "UniqueDirectivesPerLocation", - "schema": 0, - "query": "\n fragment Test on Type @directive @directive {\n field @directive @directive\n }\n ", - "errors": [ - { - "message": "The directive \"directive\" can only be used once at this location.", - "locations": [ - { - "line": 2, - "column": 29 - }, - { - "line": 2, - "column": 40 - } - ] - }, - { - "message": "The directive \"directive\" can only be used once at this location.", - "locations": [ - { - "line": 3, - "column": 15 - }, - { - "line": 3, - "column": 26 - } - ] - } - ] - }, - { - "name": "Validate: Unique fragment names/no fragments", - "rule": "UniqueFragmentNames", - "schema": 0, - "query": "\n {\n field\n }\n ", - "errors": [] - }, - { - "name": "Validate: Unique fragment names/one fragment", - "rule": "UniqueFragmentNames", - "schema": 0, - "query": "\n {\n ...fragA\n }\n\n fragment fragA on Type {\n field\n }\n ", - "errors": [] - }, - { - "name": "Validate: Unique fragment names/many fragments", - "rule": "UniqueFragmentNames", - "schema": 0, - "query": "\n {\n ...fragA\n ...fragB\n ...fragC\n }\n fragment fragA on Type {\n fieldA\n }\n fragment fragB on Type {\n fieldB\n }\n fragment fragC on Type {\n fieldC\n }\n ", - "errors": [] - }, - { - "name": "Validate: Unique fragment names/inline fragments are always unique", - "rule": "UniqueFragmentNames", - "schema": 0, - "query": "\n {\n ...on Type {\n fieldA\n }\n ...on Type {\n fieldB\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Unique fragment names/fragment and operation named the same", - "rule": "UniqueFragmentNames", - "schema": 0, - "query": "\n query Foo {\n ...Foo\n }\n fragment Foo on Type {\n field\n }\n ", - "errors": [] - }, - { - "name": "Validate: Unique fragment names/fragments named the same", - "rule": "UniqueFragmentNames", - "schema": 0, - "query": "\n {\n ...fragA\n }\n fragment fragA on Type {\n fieldA\n }\n fragment fragA on Type {\n fieldB\n }\n ", - "errors": [ - { - "message": "There can be only one fragment named \"fragA\".", - "locations": [ - { - "line": 5, - "column": 16 - }, - { - "line": 8, - "column": 16 - } - ] - } - ] - }, - { - "name": "Validate: Unique fragment names/fragments named the same without being referenced", - "rule": "UniqueFragmentNames", - "schema": 0, - "query": "\n fragment fragA on Type {\n fieldA\n }\n fragment fragA on Type {\n fieldB\n }\n ", - "errors": [ - { - "message": "There can be only one fragment named \"fragA\".", - "locations": [ - { - "line": 2, - "column": 16 - }, - { - "line": 5, - "column": 16 - } - ] - } - ] - }, - { - "name": "Validate: Unique input field names/input object with fields", - "rule": "UniqueInputFieldNames", - "schema": 0, - "query": "\n {\n field(arg: { f: true })\n }\n ", - "errors": [] - }, - { - "name": "Validate: Unique input field names/same input object within two args", - "rule": "UniqueInputFieldNames", - "schema": 0, - "query": "\n {\n field(arg1: { f: true }, arg2: { f: true })\n }\n ", - "errors": [] - }, - { - "name": "Validate: Unique input field names/multiple input object fields", - "rule": "UniqueInputFieldNames", - "schema": 0, - "query": "\n {\n field(arg: { f1: \"value\", f2: \"value\", f3: \"value\" })\n }\n ", - "errors": [] - }, - { - "name": "Validate: Unique input field names/allows for nested input objects with similar fields", - "rule": "UniqueInputFieldNames", - "schema": 0, - "query": "\n {\n field(arg: {\n deep: {\n deep: {\n id: 1\n }\n id: 1\n }\n id: 1\n })\n }\n ", - "errors": [] - }, - { - "name": "Validate: Unique input field names/duplicate input object fields", - "rule": "UniqueInputFieldNames", - "schema": 0, - "query": "\n {\n field(arg: { f1: \"value\", f1: \"value\" })\n }\n ", - "errors": [ - { - "message": "There can be only one input field named \"f1\".", - "locations": [ - { - "line": 3, - "column": 22 - }, - { - "line": 3, - "column": 35 - } - ] - } - ] - }, - { - "name": "Validate: Unique input field names/many duplicate input object fields", - "rule": "UniqueInputFieldNames", - "schema": 0, - "query": "\n {\n field(arg: { f1: \"value\", f1: \"value\", f1: \"value\" })\n }\n ", - "errors": [ - { - "message": "There can be only one input field named \"f1\".", - "locations": [ - { - "line": 3, - "column": 22 - }, - { - "line": 3, - "column": 35 - } - ] - }, - { - "message": "There can be only one input field named \"f1\".", - "locations": [ - { - "line": 3, - "column": 22 - }, - { - "line": 3, - "column": 48 - } - ] - } - ] - }, - { - "name": "Validate: Unique operation names/no operations", - "rule": "UniqueOperationNames", - "schema": 0, - "query": "\n fragment fragA on Type {\n field\n }\n ", - "errors": [] - }, - { - "name": "Validate: Unique operation names/one anon operation", - "rule": "UniqueOperationNames", - "schema": 0, - "query": "\n {\n field\n }\n ", - "errors": [] - }, - { - "name": "Validate: Unique operation names/one named operation", - "rule": "UniqueOperationNames", - "schema": 0, - "query": "\n query Foo {\n field\n }\n ", - "errors": [] - }, - { - "name": "Validate: Unique operation names/multiple operations", - "rule": "UniqueOperationNames", - "schema": 0, - "query": "\n query Foo {\n field\n }\n\n query Bar {\n field\n }\n ", - "errors": [] - }, - { - "name": "Validate: Unique operation names/multiple operations of different types", - "rule": "UniqueOperationNames", - "schema": 0, - "query": "\n query Foo {\n field\n }\n\n mutation Bar {\n field\n }\n\n subscription Baz {\n field\n }\n ", - "errors": [] - }, - { - "name": "Validate: Unique operation names/fragment and operation named the same", - "rule": "UniqueOperationNames", - "schema": 0, - "query": "\n query Foo {\n ...Foo\n }\n fragment Foo on Type {\n field\n }\n ", - "errors": [] - }, - { - "name": "Validate: Unique operation names/multiple operations of same name", - "rule": "UniqueOperationNames", - "schema": 0, - "query": "\n query Foo {\n fieldA\n }\n query Foo {\n fieldB\n }\n ", - "errors": [ - { - "message": "There can be only one operation named \"Foo\".", - "locations": [ - { - "line": 2, - "column": 13 - }, - { - "line": 5, - "column": 13 - } - ] - } - ] - }, - { - "name": "Validate: Unique operation names/multiple ops of same name of different types (mutation)", - "rule": "UniqueOperationNames", - "schema": 0, - "query": "\n query Foo {\n fieldA\n }\n mutation Foo {\n fieldB\n }\n ", - "errors": [ - { - "message": "There can be only one operation named \"Foo\".", - "locations": [ - { - "line": 2, - "column": 13 - }, - { - "line": 5, - "column": 16 - } - ] - } - ] - }, - { - "name": "Validate: Unique operation names/multiple ops of same name of different types (subscription)", - "rule": "UniqueOperationNames", - "schema": 0, - "query": "\n query Foo {\n fieldA\n }\n subscription Foo {\n fieldB\n }\n ", - "errors": [ - { - "message": "There can be only one operation named \"Foo\".", - "locations": [ - { - "line": 2, - "column": 13 - }, - { - "line": 5, - "column": 20 - } - ] - } - ] - }, - { - "name": "Validate: Unique variable names/unique variable names", - "rule": "UniqueVariableNames", - "schema": 0, - "query": "\n query A($x: Int, $y: String) { __typename }\n query B($x: String, $y: Int) { __typename }\n ", - "errors": [] - }, - { - "name": "Validate: Unique variable names/duplicate variable names", - "rule": "UniqueVariableNames", - "schema": 0, - "query": "\n query A($x: Int, $x: Int, $x: String) { __typename }\n query B($x: String, $x: Int) { __typename }\n query C($x: Int, $x: Int) { __typename }\n ", - "errors": [ - { - "message": "There can be only one variable named \"x\".", - "locations": [ - { - "line": 2, - "column": 16 - }, - { - "line": 2, - "column": 25 - } - ] - }, - { - "message": "There can be only one variable named \"x\".", - "locations": [ - { - "line": 2, - "column": 16 - }, - { - "line": 2, - "column": 34 - } - ] - }, - { - "message": "There can be only one variable named \"x\".", - "locations": [ - { - "line": 3, - "column": 16 - }, - { - "line": 3, - "column": 28 - } - ] - }, - { - "message": "There can be only one variable named \"x\".", - "locations": [ - { - "line": 4, - "column": 16 - }, - { - "line": 4, - "column": 25 - } - ] - } - ] - }, - { - "name": "Validate: Variables are input types/input types are valid", - "rule": "VariablesAreInputTypes", - "schema": 0, - "query": "\n query Foo($a: String, $b: [Boolean!]!, $c: ComplexInput) {\n field(a: $a, b: $b, c: $c)\n }\n ", - "errors": [] - }, - { - "name": "Validate: Variables are input types/output types are invalid", - "rule": "VariablesAreInputTypes", - "schema": 0, - "query": "\n query Foo($a: Dog, $b: [[CatOrDog!]]!, $c: Pet) {\n field(a: $a, b: $b, c: $c)\n }\n ", - "errors": [ - { - "locations": [ - { - "line": 2, - "column": 21 - } - ], - "message": "Variable \"$a\" cannot be non-input type \"Dog\"." - }, - { - "locations": [ - { - "line": 2, - "column": 30 - } - ], - "message": "Variable \"$b\" cannot be non-input type \"[[CatOrDog!]]!\"." - }, - { - "locations": [ - { - "line": 2, - "column": 50 - } - ], - "message": "Variable \"$c\" cannot be non-input type \"Pet\"." - } - ] - }, - { - "name": "Validate: Variables are in allowed positions/Boolean => Boolean", - "rule": "VariablesInAllowedPosition", - "schema": 0, - "query": "\n query Query($booleanArg: Boolean)\n {\n complicatedArgs {\n booleanArgField(booleanArg: $booleanArg)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Variables are in allowed positions/Boolean => Boolean within fragment", - "rule": "VariablesInAllowedPosition", - "schema": 0, - "query": "\n fragment booleanArgFrag on ComplicatedArgs {\n booleanArgField(booleanArg: $booleanArg)\n }\n query Query($booleanArg: Boolean)\n {\n complicatedArgs {\n ...booleanArgFrag\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Variables are in allowed positions/Boolean => Boolean within fragment", - "rule": "VariablesInAllowedPosition", - "schema": 0, - "query": "\n query Query($booleanArg: Boolean)\n {\n complicatedArgs {\n ...booleanArgFrag\n }\n }\n fragment booleanArgFrag on ComplicatedArgs {\n booleanArgField(booleanArg: $booleanArg)\n }\n ", - "errors": [] - }, - { - "name": "Validate: Variables are in allowed positions/Boolean! => Boolean", - "rule": "VariablesInAllowedPosition", - "schema": 0, - "query": "\n query Query($nonNullBooleanArg: Boolean!)\n {\n complicatedArgs {\n booleanArgField(booleanArg: $nonNullBooleanArg)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Variables are in allowed positions/Boolean! => Boolean within fragment", - "rule": "VariablesInAllowedPosition", - "schema": 0, - "query": "\n fragment booleanArgFrag on ComplicatedArgs {\n booleanArgField(booleanArg: $nonNullBooleanArg)\n }\n\n query Query($nonNullBooleanArg: Boolean!)\n {\n complicatedArgs {\n ...booleanArgFrag\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Variables are in allowed positions/Int => Int! with default", - "rule": "VariablesInAllowedPosition", - "schema": 0, - "query": "\n query Query($intArg: Int = 1)\n {\n complicatedArgs {\n nonNullIntArgField(nonNullIntArg: $intArg)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Variables are in allowed positions/[String] => [String]", - "rule": "VariablesInAllowedPosition", - "schema": 0, - "query": "\n query Query($stringListVar: [String])\n {\n complicatedArgs {\n stringListArgField(stringListArg: $stringListVar)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Variables are in allowed positions/[String!] => [String]", - "rule": "VariablesInAllowedPosition", - "schema": 0, - "query": "\n query Query($stringListVar: [String!])\n {\n complicatedArgs {\n stringListArgField(stringListArg: $stringListVar)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Variables are in allowed positions/String => [String] in item position", - "rule": "VariablesInAllowedPosition", - "schema": 0, - "query": "\n query Query($stringVar: String)\n {\n complicatedArgs {\n stringListArgField(stringListArg: [$stringVar])\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Variables are in allowed positions/String! => [String] in item position", - "rule": "VariablesInAllowedPosition", - "schema": 0, - "query": "\n query Query($stringVar: String!)\n {\n complicatedArgs {\n stringListArgField(stringListArg: [$stringVar])\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Variables are in allowed positions/ComplexInput => ComplexInput", - "rule": "VariablesInAllowedPosition", - "schema": 0, - "query": "\n query Query($complexVar: ComplexInput)\n {\n complicatedArgs {\n complexArgField(complexArg: $complexVar)\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Variables are in allowed positions/ComplexInput => ComplexInput in field position", - "rule": "VariablesInAllowedPosition", - "schema": 0, - "query": "\n query Query($boolVar: Boolean = false)\n {\n complicatedArgs {\n complexArgField(complexArg: {requiredArg: $boolVar})\n }\n }\n ", - "errors": [] - }, - { - "name": "Validate: Variables are in allowed positions/Boolean! => Boolean! in directive", - "rule": "VariablesInAllowedPosition", - "schema": 0, - "query": "\n query Query($boolVar: Boolean!)\n {\n dog @include(if: $boolVar)\n }\n ", - "errors": [] - }, - { - "name": "Validate: Variables are in allowed positions/Boolean => Boolean! in directive with default", - "rule": "VariablesInAllowedPosition", - "schema": 0, - "query": "\n query Query($boolVar: Boolean = false)\n {\n dog @include(if: $boolVar)\n }\n ", - "errors": [] - }, - { - "name": "Validate: Variables are in allowed positions/Int => Int!", - "rule": "VariablesInAllowedPosition", - "schema": 0, - "query": "\n query Query($intArg: Int) {\n complicatedArgs {\n nonNullIntArgField(nonNullIntArg: $intArg)\n }\n }\n ", - "errors": [ - { - "message": "Variable \"$intArg\" of type \"Int\" used in position expecting type \"Int!\".", - "locations": [ - { - "line": 2, - "column": 19 - }, - { - "line": 4, - "column": 45 - } - ] - } - ] - }, - { - "name": "Validate: Variables are in allowed positions/Int => Int! within fragment", - "rule": "VariablesInAllowedPosition", - "schema": 0, - "query": "\n fragment nonNullIntArgFieldFrag on ComplicatedArgs {\n nonNullIntArgField(nonNullIntArg: $intArg)\n }\n\n query Query($intArg: Int) {\n complicatedArgs {\n ...nonNullIntArgFieldFrag\n }\n }\n ", - "errors": [ - { - "message": "Variable \"$intArg\" of type \"Int\" used in position expecting type \"Int!\".", - "locations": [ - { - "line": 6, - "column": 19 - }, - { - "line": 3, - "column": 43 - } - ] - } - ] - }, - { - "name": "Validate: Variables are in allowed positions/Int => Int! within nested fragment", - "rule": "VariablesInAllowedPosition", - "schema": 0, - "query": "\n fragment outerFrag on ComplicatedArgs {\n ...nonNullIntArgFieldFrag\n }\n\n fragment nonNullIntArgFieldFrag on ComplicatedArgs {\n nonNullIntArgField(nonNullIntArg: $intArg)\n }\n\n query Query($intArg: Int) {\n complicatedArgs {\n ...outerFrag\n }\n }\n ", - "errors": [ - { - "message": "Variable \"$intArg\" of type \"Int\" used in position expecting type \"Int!\".", - "locations": [ - { - "line": 10, - "column": 19 - }, - { - "line": 7, - "column": 43 - } - ] - } - ] - }, - { - "name": "Validate: Variables are in allowed positions/String over Boolean", - "rule": "VariablesInAllowedPosition", - "schema": 0, - "query": "\n query Query($stringVar: String) {\n complicatedArgs {\n booleanArgField(booleanArg: $stringVar)\n }\n }\n ", - "errors": [ - { - "message": "Variable \"$stringVar\" of type \"String\" used in position expecting type \"Boolean\".", - "locations": [ - { - "line": 2, - "column": 19 - }, - { - "line": 4, - "column": 39 - } - ] - } - ] - }, - { - "name": "Validate: Variables are in allowed positions/String => [String]", - "rule": "VariablesInAllowedPosition", - "schema": 0, - "query": "\n query Query($stringVar: String) {\n complicatedArgs {\n stringListArgField(stringListArg: $stringVar)\n }\n }\n ", - "errors": [ - { - "message": "Variable \"$stringVar\" of type \"String\" used in position expecting type \"[String]\".", - "locations": [ - { - "line": 2, - "column": 19 - }, - { - "line": 4, - "column": 45 - } - ] - } - ] - }, - { - "name": "Validate: Variables are in allowed positions/Boolean => Boolean! in directive", - "rule": "VariablesInAllowedPosition", - "schema": 0, - "query": "\n query Query($boolVar: Boolean) {\n dog @include(if: $boolVar)\n }\n ", - "errors": [ - { - "message": "Variable \"$boolVar\" of type \"Boolean\" used in position expecting type \"Boolean!\".", - "locations": [ - { - "line": 2, - "column": 19 - }, - { - "line": 3, - "column": 26 - } - ] - } - ] - }, - { - "name": "Validate: Variables are in allowed positions/String => Boolean! in directive", - "rule": "VariablesInAllowedPosition", - "schema": 0, - "query": "\n query Query($stringVar: String) {\n dog @include(if: $stringVar)\n }\n ", - "errors": [ - { - "message": "Variable \"$stringVar\" of type \"String\" used in position expecting type \"Boolean!\".", - "locations": [ - { - "line": 2, - "column": 19 - }, - { - "line": 3, - "column": 26 - } - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/neelance/validation/suggestion.go b/neelance/validation/suggestion.go deleted file mode 100644 index 9702b5f5294..00000000000 --- a/neelance/validation/suggestion.go +++ /dev/null @@ -1,71 +0,0 @@ -package validation - -import ( - "fmt" - "sort" - "strconv" - "strings" -) - -func makeSuggestion(prefix string, options []string, input string) string { - var selected []string - distances := make(map[string]int) - for _, opt := range options { - distance := levenshteinDistance(input, opt) - threshold := max(len(input)/2, max(len(opt)/2, 1)) - if distance < threshold { - selected = append(selected, opt) - distances[opt] = distance - } - } - - if len(selected) == 0 { - return "" - } - sort.Slice(selected, func(i, j int) bool { - return distances[selected[i]] < distances[selected[j]] - }) - - parts := make([]string, len(selected)) - for i, opt := range selected { - parts[i] = strconv.Quote(opt) - } - if len(parts) > 1 { - parts[len(parts)-1] = "or " + parts[len(parts)-1] - } - return fmt.Sprintf(" %s %s?", prefix, strings.Join(parts, ", ")) -} - -func levenshteinDistance(s1, s2 string) int { - column := make([]int, len(s1)+1) - for y := range s1 { - column[y+1] = y + 1 - } - for x, rx := range s2 { - column[0] = x + 1 - lastdiag := x - for y, ry := range s1 { - olddiag := column[y+1] - if rx != ry { - lastdiag++ - } - column[y+1] = min(column[y+1]+1, min(column[y]+1, lastdiag)) - lastdiag = olddiag - } - } - return column[len(s1)] -} - -func min(a, b int) int { - if a < b { - return a - } - return b -} - -func max(a, b int) int { - if a > b { - return a - } - return b -} diff --git a/neelance/validation/validation.go b/neelance/validation/validation.go deleted file mode 100644 index 28124310a00..00000000000 --- a/neelance/validation/validation.go +++ /dev/null @@ -1,861 +0,0 @@ -package validation - -import ( - "fmt" - "math" - "reflect" - "strconv" - "strings" - "text/scanner" - - "github.com/vektah/gqlgen/neelance/common" - "github.com/vektah/gqlgen/neelance/errors" - "github.com/vektah/gqlgen/neelance/query" - "github.com/vektah/gqlgen/neelance/schema" -) - -type varSet map[*common.InputValue]struct{} - -type selectionPair struct{ a, b query.Selection } - -type fieldInfo struct { - sf *schema.Field - parent schema.NamedType -} - -type context struct { - schema *schema.Schema - doc *query.Document - errs []*errors.QueryError - opErrs map[*query.Operation][]*errors.QueryError - usedVars map[*query.Operation]varSet - fieldMap map[*query.Field]fieldInfo - overlapValidated map[selectionPair]struct{} -} - -func (c *context) addErr(loc errors.Location, rule string, format string, a ...interface{}) { - c.addErrMultiLoc([]errors.Location{loc}, rule, format, a...) -} - -func (c *context) addErrMultiLoc(locs []errors.Location, rule string, format string, a ...interface{}) { - c.errs = append(c.errs, &errors.QueryError{ - Message: fmt.Sprintf(format, a...), - Locations: locs, - Rule: rule, - }) -} - -type opContext struct { - *context - ops []*query.Operation -} - -func Validate(s *schema.Schema, doc *query.Document) []*errors.QueryError { - c := &context{ - schema: s, - doc: doc, - opErrs: make(map[*query.Operation][]*errors.QueryError), - usedVars: make(map[*query.Operation]varSet), - fieldMap: make(map[*query.Field]fieldInfo), - overlapValidated: make(map[selectionPair]struct{}), - } - - opNames := make(nameSet) - fragUsedBy := make(map[*query.FragmentDecl][]*query.Operation) - for _, op := range doc.Operations { - c.usedVars[op] = make(varSet) - opc := &opContext{c, []*query.Operation{op}} - - if op.Name.Name == "" && len(doc.Operations) != 1 { - c.addErr(op.Loc, "LoneAnonymousOperation", "This anonymous operation must be the only defined operation.") - } - if op.Name.Name != "" { - validateName(c, opNames, op.Name, "UniqueOperationNames", "operation") - } - - validateDirectives(opc, string(op.Type), op.Directives) - - varNames := make(nameSet) - for _, v := range op.Vars { - validateName(c, varNames, v.Name, "UniqueVariableNames", "variable") - - t := resolveType(c, v.Type) - if !canBeInput(t) { - c.addErr(v.TypeLoc, "VariablesAreInputTypes", "Variable %q cannot be non-input type %q.", "$"+v.Name.Name, t) - } - - if v.Default != nil { - validateLiteral(opc, v.Default) - - if t != nil { - if nn, ok := t.(*common.NonNull); ok { - c.addErr(v.Default.Location(), "DefaultValuesOfCorrectType", "Variable %q of type %q is required and will not use the default value. Perhaps you meant to use type %q.", "$"+v.Name.Name, t, nn.OfType) - } - - if ok, reason := validateValueType(opc, v.Default, t); !ok { - c.addErr(v.Default.Location(), "DefaultValuesOfCorrectType", "Variable %q of type %q has invalid default value %s.\n%s", "$"+v.Name.Name, t, v.Default, reason) - } - } - } - } - - var entryPoint schema.NamedType - switch op.Type { - case query.Query: - entryPoint = s.EntryPoints["query"] - case query.Mutation: - entryPoint = s.EntryPoints["mutation"] - case query.Subscription: - entryPoint = s.EntryPoints["subscription"] - default: - panic("unreachable") - } - - validateSelectionSet(opc, op.Selections, entryPoint) - - fragUsed := make(map[*query.FragmentDecl]struct{}) - markUsedFragments(c, op.Selections, fragUsed) - for frag := range fragUsed { - fragUsedBy[frag] = append(fragUsedBy[frag], op) - } - } - - fragNames := make(nameSet) - fragVisited := make(map[*query.FragmentDecl]struct{}) - for _, frag := range doc.Fragments { - opc := &opContext{c, fragUsedBy[frag]} - - validateName(c, fragNames, frag.Name, "UniqueFragmentNames", "fragment") - validateDirectives(opc, "FRAGMENT_DEFINITION", frag.Directives) - - t := unwrapType(resolveType(c, &frag.On)) - // continue even if t is nil - if t != nil && !canBeFragment(t) { - c.addErr(frag.On.Loc, "FragmentsOnCompositeTypes", "Fragment %q cannot condition on non composite type %q.", frag.Name.Name, t) - continue - } - - validateSelectionSet(opc, frag.Selections, t) - - if _, ok := fragVisited[frag]; !ok { - detectFragmentCycle(c, frag.Selections, fragVisited, nil, map[string]int{frag.Name.Name: 0}) - } - } - - for _, frag := range doc.Fragments { - if len(fragUsedBy[frag]) == 0 { - c.addErr(frag.Loc, "NoUnusedFragments", "Fragment %q is never used.", frag.Name.Name) - } - } - - for _, op := range doc.Operations { - c.errs = append(c.errs, c.opErrs[op]...) - - opUsedVars := c.usedVars[op] - for _, v := range op.Vars { - if _, ok := opUsedVars[v]; !ok { - opSuffix := "" - if op.Name.Name != "" { - opSuffix = fmt.Sprintf(" in operation %q", op.Name.Name) - } - c.addErr(v.Loc, "NoUnusedVariables", "Variable %q is never used%s.", "$"+v.Name.Name, opSuffix) - } - } - } - - return c.errs -} - -func validateSelectionSet(c *opContext, sels []query.Selection, t schema.NamedType) { - for _, sel := range sels { - validateSelection(c, sel, t) - } - - for i, a := range sels { - for _, b := range sels[i+1:] { - c.validateOverlap(a, b, nil, nil) - } - } -} - -func validateSelection(c *opContext, sel query.Selection, t schema.NamedType) { - switch sel := sel.(type) { - case *query.Field: - validateDirectives(c, "FIELD", sel.Directives) - - fieldName := sel.Name.Name - var f *schema.Field - switch fieldName { - case "__typename": - f = &schema.Field{ - Name: "__typename", - Type: c.schema.Types["String"], - } - case "__schema": - f = &schema.Field{ - Name: "__schema", - Type: c.schema.Types["__Schema"], - } - case "__type": - f = &schema.Field{ - Name: "__type", - Args: common.InputValueList{ - &common.InputValue{ - Name: common.Ident{Name: "name"}, - Type: &common.NonNull{OfType: c.schema.Types["String"]}, - }, - }, - Type: c.schema.Types["__Type"], - } - default: - f = fields(t).Get(fieldName) - if f == nil && t != nil { - suggestion := makeSuggestion("Did you mean", fields(t).Names(), fieldName) - c.addErr(sel.Alias.Loc, "FieldsOnCorrectType", "Cannot query field %q on type %q.%s", fieldName, t, suggestion) - } - } - c.fieldMap[sel] = fieldInfo{sf: f, parent: t} - - validateArgumentLiterals(c, sel.Arguments) - if f != nil { - validateArgumentTypes(c, sel.Arguments, f.Args, sel.Alias.Loc, - func() string { return fmt.Sprintf("field %q of type %q", fieldName, t) }, - func() string { return fmt.Sprintf("Field %q", fieldName) }, - ) - } - - var ft common.Type - if f != nil { - ft = f.Type - sf := hasSubfields(ft) - if sf && sel.Selections == nil { - c.addErr(sel.Alias.Loc, "ScalarLeafs", "Field %q of type %q must have a selection of subfields. Did you mean \"%s { ... }\"?", fieldName, ft, fieldName) - } - if !sf && sel.Selections != nil { - c.addErr(sel.SelectionSetLoc, "ScalarLeafs", "Field %q must not have a selection since type %q has no subfields.", fieldName, ft) - } - } - if sel.Selections != nil { - validateSelectionSet(c, sel.Selections, unwrapType(ft)) - } - - case *query.InlineFragment: - validateDirectives(c, "INLINE_FRAGMENT", sel.Directives) - if sel.On.Name != "" { - fragTyp := unwrapType(resolveType(c.context, &sel.On)) - if fragTyp != nil && !compatible(t, fragTyp) { - c.addErr(sel.Loc, "PossibleFragmentSpreads", "Fragment cannot be spread here as objects of type %q can never be of type %q.", t, fragTyp) - } - t = fragTyp - // continue even if t is nil - } - if t != nil && !canBeFragment(t) { - c.addErr(sel.On.Loc, "FragmentsOnCompositeTypes", "Fragment cannot condition on non composite type %q.", t) - return - } - validateSelectionSet(c, sel.Selections, unwrapType(t)) - - case *query.FragmentSpread: - validateDirectives(c, "FRAGMENT_SPREAD", sel.Directives) - frag := c.doc.Fragments.Get(sel.Name.Name) - if frag == nil { - c.addErr(sel.Name.Loc, "KnownFragmentNames", "Unknown fragment %q.", sel.Name.Name) - return - } - fragTyp := c.schema.Types[frag.On.Name] - if !compatible(t, fragTyp) { - c.addErr(sel.Loc, "PossibleFragmentSpreads", "Fragment %q cannot be spread here as objects of type %q can never be of type %q.", frag.Name.Name, t, fragTyp) - } - - default: - panic("unreachable") - } -} - -func compatible(a, b common.Type) bool { - for _, pta := range possibleTypes(a) { - for _, ptb := range possibleTypes(b) { - if pta == ptb { - return true - } - } - } - return false -} - -func possibleTypes(t common.Type) []*schema.Object { - switch t := t.(type) { - case *schema.Object: - return []*schema.Object{t} - case *schema.Interface: - return t.PossibleTypes - case *schema.Union: - return t.PossibleTypes - default: - return nil - } -} - -func markUsedFragments(c *context, sels []query.Selection, fragUsed map[*query.FragmentDecl]struct{}) { - for _, sel := range sels { - switch sel := sel.(type) { - case *query.Field: - if sel.Selections != nil { - markUsedFragments(c, sel.Selections, fragUsed) - } - - case *query.InlineFragment: - markUsedFragments(c, sel.Selections, fragUsed) - - case *query.FragmentSpread: - frag := c.doc.Fragments.Get(sel.Name.Name) - if frag == nil { - return - } - - if _, ok := fragUsed[frag]; ok { - return - } - fragUsed[frag] = struct{}{} - markUsedFragments(c, frag.Selections, fragUsed) - - default: - panic("unreachable") - } - } -} - -func detectFragmentCycle(c *context, sels []query.Selection, fragVisited map[*query.FragmentDecl]struct{}, spreadPath []*query.FragmentSpread, spreadPathIndex map[string]int) { - for _, sel := range sels { - detectFragmentCycleSel(c, sel, fragVisited, spreadPath, spreadPathIndex) - } -} - -func detectFragmentCycleSel(c *context, sel query.Selection, fragVisited map[*query.FragmentDecl]struct{}, spreadPath []*query.FragmentSpread, spreadPathIndex map[string]int) { - switch sel := sel.(type) { - case *query.Field: - if sel.Selections != nil { - detectFragmentCycle(c, sel.Selections, fragVisited, spreadPath, spreadPathIndex) - } - - case *query.InlineFragment: - detectFragmentCycle(c, sel.Selections, fragVisited, spreadPath, spreadPathIndex) - - case *query.FragmentSpread: - frag := c.doc.Fragments.Get(sel.Name.Name) - if frag == nil { - return - } - - spreadPath = append(spreadPath, sel) - if i, ok := spreadPathIndex[frag.Name.Name]; ok { - cyclePath := spreadPath[i:] - via := "" - if len(cyclePath) > 1 { - names := make([]string, len(cyclePath)-1) - for i, frag := range cyclePath[:len(cyclePath)-1] { - names[i] = frag.Name.Name - } - via = " via " + strings.Join(names, ", ") - } - - locs := make([]errors.Location, len(cyclePath)) - for i, frag := range cyclePath { - locs[i] = frag.Loc - } - c.addErrMultiLoc(locs, "NoFragmentCycles", "Cannot spread fragment %q within itself%s.", frag.Name.Name, via) - return - } - - if _, ok := fragVisited[frag]; ok { - return - } - fragVisited[frag] = struct{}{} - - spreadPathIndex[frag.Name.Name] = len(spreadPath) - detectFragmentCycle(c, frag.Selections, fragVisited, spreadPath, spreadPathIndex) - delete(spreadPathIndex, frag.Name.Name) - - default: - panic("unreachable") - } -} - -func (c *context) validateOverlap(a, b query.Selection, reasons *[]string, locs *[]errors.Location) { - if a == b { - return - } - - if _, ok := c.overlapValidated[selectionPair{a, b}]; ok { - return - } - c.overlapValidated[selectionPair{a, b}] = struct{}{} - c.overlapValidated[selectionPair{b, a}] = struct{}{} - - switch a := a.(type) { - case *query.Field: - switch b := b.(type) { - case *query.Field: - if b.Alias.Loc.Before(a.Alias.Loc) { - a, b = b, a - } - if reasons2, locs2 := c.validateFieldOverlap(a, b); len(reasons2) != 0 { - locs2 = append(locs2, a.Alias.Loc, b.Alias.Loc) - if reasons == nil { - c.addErrMultiLoc(locs2, "OverlappingFieldsCanBeMerged", "Fields %q conflict because %s. Use different aliases on the fields to fetch both if this was intentional.", a.Alias.Name, strings.Join(reasons2, " and ")) - return - } - for _, r := range reasons2 { - *reasons = append(*reasons, fmt.Sprintf("subfields %q conflict because %s", a.Alias.Name, r)) - } - *locs = append(*locs, locs2...) - } - - case *query.InlineFragment: - for _, sel := range b.Selections { - c.validateOverlap(a, sel, reasons, locs) - } - - case *query.FragmentSpread: - if frag := c.doc.Fragments.Get(b.Name.Name); frag != nil { - for _, sel := range frag.Selections { - c.validateOverlap(a, sel, reasons, locs) - } - } - - default: - panic("unreachable") - } - - case *query.InlineFragment: - for _, sel := range a.Selections { - c.validateOverlap(sel, b, reasons, locs) - } - - case *query.FragmentSpread: - if frag := c.doc.Fragments.Get(a.Name.Name); frag != nil { - for _, sel := range frag.Selections { - c.validateOverlap(sel, b, reasons, locs) - } - } - - default: - panic("unreachable") - } -} - -func (c *context) validateFieldOverlap(a, b *query.Field) ([]string, []errors.Location) { - if a.Alias.Name != b.Alias.Name { - return nil, nil - } - - if asf := c.fieldMap[a].sf; asf != nil { - if bsf := c.fieldMap[b].sf; bsf != nil { - if !typesCompatible(asf.Type, bsf.Type) { - return []string{fmt.Sprintf("they return conflicting types %s and %s", asf.Type, bsf.Type)}, nil - } - } - } - - at := c.fieldMap[a].parent - bt := c.fieldMap[b].parent - if at == nil || bt == nil || at == bt { - if a.Name.Name != b.Name.Name { - return []string{fmt.Sprintf("%s and %s are different fields", a.Name.Name, b.Name.Name)}, nil - } - - if argumentsConflict(a.Arguments, b.Arguments) { - return []string{"they have differing arguments"}, nil - } - } - - var reasons []string - var locs []errors.Location - for _, a2 := range a.Selections { - for _, b2 := range b.Selections { - c.validateOverlap(a2, b2, &reasons, &locs) - } - } - return reasons, locs -} - -func argumentsConflict(a, b common.ArgumentList) bool { - if len(a) != len(b) { - return true - } - for _, argA := range a { - valB, ok := b.Get(argA.Name.Name) - if !ok || !reflect.DeepEqual(argA.Value.Value(nil), valB.Value(nil)) { - return true - } - } - return false -} - -func fields(t common.Type) schema.FieldList { - switch t := t.(type) { - case *schema.Object: - return t.Fields - case *schema.Interface: - return t.Fields - default: - return nil - } -} - -func unwrapType(t common.Type) schema.NamedType { - if t == nil { - return nil - } - for { - switch t2 := t.(type) { - case schema.NamedType: - return t2 - case *common.List: - t = t2.OfType - case *common.NonNull: - t = t2.OfType - default: - panic("unreachable") - } - } -} - -func resolveType(c *context, t common.Type) common.Type { - t2, err := common.ResolveType(t, c.schema.Resolve) - if err != nil { - c.errs = append(c.errs, err) - } - return t2 -} - -func validateDirectives(c *opContext, loc string, directives common.DirectiveList) { - directiveNames := make(nameSet) - for _, d := range directives { - dirName := d.Name.Name - validateNameCustomMsg(c.context, directiveNames, d.Name, "UniqueDirectivesPerLocation", func() string { - return fmt.Sprintf("The directive %q can only be used once at this location.", dirName) - }) - - validateArgumentLiterals(c, d.Args) - - dd, ok := c.schema.Directives[dirName] - if !ok { - c.addErr(d.Name.Loc, "KnownDirectives", "Unknown directive %q.", dirName) - continue - } - - locOK := false - for _, allowedLoc := range dd.Locs { - if loc == allowedLoc { - locOK = true - break - } - } - if !locOK { - c.addErr(d.Name.Loc, "KnownDirectives", "Directive %q may not be used on %s.", dirName, loc) - } - - validateArgumentTypes(c, d.Args, dd.Args, d.Name.Loc, - func() string { return fmt.Sprintf("directive %q", "@"+dirName) }, - func() string { return fmt.Sprintf("Directive %q", "@"+dirName) }, - ) - } -} - -type nameSet map[string]errors.Location - -func validateName(c *context, set nameSet, name common.Ident, rule string, kind string) { - validateNameCustomMsg(c, set, name, rule, func() string { - return fmt.Sprintf("There can be only one %s named %q.", kind, name.Name) - }) -} - -func validateNameCustomMsg(c *context, set nameSet, name common.Ident, rule string, msg func() string) { - if loc, ok := set[name.Name]; ok { - c.addErrMultiLoc([]errors.Location{loc, name.Loc}, rule, msg()) - return - } - set[name.Name] = name.Loc -} - -func validateArgumentTypes(c *opContext, args common.ArgumentList, argDecls common.InputValueList, loc errors.Location, owner1, owner2 func() string) { - for _, selArg := range args { - arg := argDecls.Get(selArg.Name.Name) - if arg == nil { - c.addErr(selArg.Name.Loc, "KnownArgumentNames", "Unknown argument %q on %s.", selArg.Name.Name, owner1()) - continue - } - value := selArg.Value - if ok, reason := validateValueType(c, value, arg.Type); !ok { - c.addErr(value.Location(), "ArgumentsOfCorrectType", "Argument %q has invalid value %s.\n%s", arg.Name.Name, value, reason) - } - } - for _, decl := range argDecls { - if _, ok := decl.Type.(*common.NonNull); ok { - if _, ok := args.Get(decl.Name.Name); !ok { - c.addErr(loc, "ProvidedNonNullArguments", "%s argument %q of type %q is required but not provided.", owner2(), decl.Name.Name, decl.Type) - } - } - } -} - -func validateArgumentLiterals(c *opContext, args common.ArgumentList) { - argNames := make(nameSet) - for _, arg := range args { - validateName(c.context, argNames, arg.Name, "UniqueArgumentNames", "argument") - validateLiteral(c, arg.Value) - } -} - -func validateLiteral(c *opContext, l common.Literal) { - switch l := l.(type) { - case *common.ObjectLit: - fieldNames := make(nameSet) - for _, f := range l.Fields { - validateName(c.context, fieldNames, f.Name, "UniqueInputFieldNames", "input field") - validateLiteral(c, f.Value) - } - case *common.ListLit: - for _, entry := range l.Entries { - validateLiteral(c, entry) - } - case *common.Variable: - for _, op := range c.ops { - v := op.Vars.Get(l.Name) - if v == nil { - byOp := "" - if op.Name.Name != "" { - byOp = fmt.Sprintf(" by operation %q", op.Name.Name) - } - c.opErrs[op] = append(c.opErrs[op], &errors.QueryError{ - Message: fmt.Sprintf("Variable %q is not defined%s.", "$"+l.Name, byOp), - Locations: []errors.Location{l.Loc, op.Loc}, - Rule: "NoUndefinedVariables", - }) - continue - } - c.usedVars[op][v] = struct{}{} - } - } -} - -func validateValueType(c *opContext, v common.Literal, t common.Type) (bool, string) { - if v, ok := v.(*common.Variable); ok { - for _, op := range c.ops { - if v2 := op.Vars.Get(v.Name); v2 != nil { - t2, err := common.ResolveType(v2.Type, c.schema.Resolve) - if _, ok := t2.(*common.NonNull); !ok && v2.Default != nil { - t2 = &common.NonNull{OfType: t2} - } - if err == nil && !typeCanBeUsedAs(t2, t) { - c.addErrMultiLoc([]errors.Location{v2.Loc, v.Loc}, "VariablesInAllowedPosition", "Variable %q of type %q used in position expecting type %q.", "$"+v.Name, t2, t) - } - } - } - return true, "" - } - - if nn, ok := t.(*common.NonNull); ok { - if isNull(v) { - return false, fmt.Sprintf("Expected %q, found null.", t) - } - t = nn.OfType - } - if isNull(v) { - return true, "" - } - - switch t := t.(type) { - case *schema.Scalar, *schema.Enum: - if lit, ok := v.(*common.BasicLit); ok { - if validateBasicLit(lit, t) { - return true, "" - } - } else { - // custom complex scalars will be validated when unmarshaling - return true, "" - } - - case *common.List: - list, ok := v.(*common.ListLit) - if !ok { - return validateValueType(c, v, t.OfType) // single value instead of list - } - for i, entry := range list.Entries { - if ok, reason := validateValueType(c, entry, t.OfType); !ok { - return false, fmt.Sprintf("In element #%d: %s", i, reason) - } - } - return true, "" - - case *schema.InputObject: - v, ok := v.(*common.ObjectLit) - if !ok { - return false, fmt.Sprintf("Expected %q, found not an object.", t) - } - for _, f := range v.Fields { - name := f.Name.Name - iv := t.Values.Get(name) - if iv == nil { - return false, fmt.Sprintf("In field %q: Unknown field.", name) - } - if ok, reason := validateValueType(c, f.Value, iv.Type); !ok { - return false, fmt.Sprintf("In field %q: %s", name, reason) - } - } - for _, iv := range t.Values { - found := false - for _, f := range v.Fields { - if f.Name.Name == iv.Name.Name { - found = true - break - } - } - if !found { - if _, ok := iv.Type.(*common.NonNull); ok && iv.Default == nil { - return false, fmt.Sprintf("In field %q: Expected %q, found null.", iv.Name.Name, iv.Type) - } - } - } - return true, "" - } - - return false, fmt.Sprintf("Expected type %q, found %s.", t, v) -} - -func validateBasicLit(v *common.BasicLit, t common.Type) bool { - switch t := t.(type) { - case *schema.Scalar: - switch t.Name { - case "Int": - if v.Type != scanner.Int { - return false - } - f, err := strconv.ParseFloat(v.Text, 64) - if err != nil { - panic(err) - } - return f >= math.MinInt32 && f <= math.MaxInt32 - case "Float": - return v.Type == scanner.Int || v.Type == scanner.Float - case "String": - return v.Type == scanner.String - case "Boolean": - return v.Type == scanner.Ident && (v.Text == "true" || v.Text == "false") - case "ID": - return v.Type == scanner.Int || v.Type == scanner.String - default: - //TODO: Type-check against expected type by Unmarshaling - return true - } - - case *schema.Enum: - if v.Type != scanner.Ident { - return false - } - for _, option := range t.Values { - if option.Name == v.Text { - return true - } - } - return false - } - - return false -} - -func canBeFragment(t common.Type) bool { - switch t.(type) { - case *schema.Object, *schema.Interface, *schema.Union: - return true - default: - return false - } -} - -func canBeInput(t common.Type) bool { - switch t := t.(type) { - case *schema.InputObject, *schema.Scalar, *schema.Enum: - return true - case *common.List: - return canBeInput(t.OfType) - case *common.NonNull: - return canBeInput(t.OfType) - default: - return false - } -} - -func hasSubfields(t common.Type) bool { - switch t := t.(type) { - case *schema.Object, *schema.Interface, *schema.Union: - return true - case *common.List: - return hasSubfields(t.OfType) - case *common.NonNull: - return hasSubfields(t.OfType) - default: - return false - } -} - -func isLeaf(t common.Type) bool { - switch t.(type) { - case *schema.Scalar, *schema.Enum: - return true - default: - return false - } -} - -func isNull(lit interface{}) bool { - _, ok := lit.(*common.NullLit) - return ok -} - -func typesCompatible(a, b common.Type) bool { - al, aIsList := a.(*common.List) - bl, bIsList := b.(*common.List) - if aIsList || bIsList { - return aIsList && bIsList && typesCompatible(al.OfType, bl.OfType) - } - - ann, aIsNN := a.(*common.NonNull) - bnn, bIsNN := b.(*common.NonNull) - if aIsNN || bIsNN { - return aIsNN && bIsNN && typesCompatible(ann.OfType, bnn.OfType) - } - - if isLeaf(a) || isLeaf(b) { - return a == b - } - - return true -} - -func typeCanBeUsedAs(t, as common.Type) bool { - nnT, okT := t.(*common.NonNull) - if okT { - t = nnT.OfType - } - - nnAs, okAs := as.(*common.NonNull) - if okAs { - as = nnAs.OfType - if !okT { - return false // nullable can not be used as non-null - } - } - - if t == as { - return true - } - - if lT, ok := t.(*common.List); ok { - if lAs, ok := as.(*common.List); ok { - return typeCanBeUsedAs(lT.OfType, lAs.OfType) - } - } - return false -} diff --git a/test/generated.go b/test/generated.go index 862060b3fd9..6e1c67b875f 100644 --- a/test/generated.go +++ b/test/generated.go @@ -9,10 +9,10 @@ import ( strconv "strconv" graphql "github.com/vektah/gqlgen/graphql" - introspection "github.com/vektah/gqlgen/neelance/introspection" - query "github.com/vektah/gqlgen/neelance/query" - schema "github.com/vektah/gqlgen/neelance/schema" + introspection "github.com/vektah/gqlgen/graphql/introspection" models "github.com/vektah/gqlgen/test/models-go" + gqlparser "github.com/vektah/gqlparser" + ast "github.com/vektah/gqlparser/ast" ) // MakeExecutableSchema creates an ExecutableSchema from the Resolvers interface. @@ -97,15 +97,15 @@ type executableSchema struct { resolvers Resolvers } -func (e *executableSchema) Schema() *schema.Schema { +func (e *executableSchema) Schema() *ast.Schema { return parsedSchema } -func (e *executableSchema) Query(ctx context.Context, op *query.Operation) *graphql.Response { +func (e *executableSchema) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers} buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte { - data := ec._Query(ctx, op.Selections) + data := ec._Query(ctx, op.SelectionSet) var buf bytes.Buffer data.MarshalGQL(&buf) return buf.Bytes() @@ -117,11 +117,11 @@ func (e *executableSchema) Query(ctx context.Context, op *query.Operation) *grap } } -func (e *executableSchema) Mutation(ctx context.Context, op *query.Operation) *graphql.Response { +func (e *executableSchema) Mutation(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { return graphql.ErrorResponse(ctx, "mutations are not supported") } -func (e *executableSchema) Subscription(ctx context.Context, op *query.Operation) func() *graphql.Response { +func (e *executableSchema) Subscription(ctx context.Context, op *ast.OperationDefinition) func() *graphql.Response { return graphql.OneShot(graphql.ErrorResponse(ctx, "subscriptions are not supported")) } @@ -134,7 +134,7 @@ type executionContext struct { var elementImplementors = []string{"Element"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Element(ctx context.Context, sel []query.Selection, obj *models.Element) graphql.Marshaler { +func (ec *executionContext) _Element(ctx context.Context, sel ast.SelectionSet, obj *models.Element) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, elementImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -260,7 +260,7 @@ func (ec *executionContext) _Element_mismatched(ctx context.Context, field graph var queryImplementors = []string{"Query"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Query(ctx context.Context, sel []query.Selection) graphql.Marshaler { +func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, queryImplementors, ec.Variables) ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{ @@ -282,10 +282,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel []query.Selection) g out.Values[i] = ec._Query_viewer(ctx, field) case "jsonEncoding": out.Values[i] = ec._Query_jsonEncoding(ctx, field) - case "__schema": - out.Values[i] = ec._Query___schema(ctx, field) case "__type": out.Values[i] = ec._Query___type(ctx, field) + case "__schema": + out.Values[i] = ec._Query___schema(ctx, field) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -440,20 +440,6 @@ func (ec *executionContext) _Query_jsonEncoding(ctx context.Context, field graph }) } -func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { - rctx := graphql.GetResolverContext(ctx) - rctx.Object = "Query" - rctx.Args = nil - rctx.Field = field - rctx.PushField(field.Alias) - defer rctx.Pop() - res := ec.introspectSchema() - if res == nil { - return graphql.Null - } - return ec.___Schema(ctx, field.Selections, res) -} - func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { args := map[string]interface{}{} var arg0 string @@ -479,10 +465,24 @@ func (ec *executionContext) _Query___type(ctx context.Context, field graphql.Col return ec.___Type(ctx, field.Selections, res) } +func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { + rctx := graphql.GetResolverContext(ctx) + rctx.Object = "Query" + rctx.Args = nil + rctx.Field = field + rctx.PushField(field.Alias) + defer rctx.Pop() + res := ec.introspectSchema() + if res == nil { + return graphql.Null + } + return ec.___Schema(ctx, field.Selections, res) +} + var userImplementors = []string{"User"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _User(ctx context.Context, sel []query.Selection, obj *remote_api.User) graphql.Marshaler { +func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj *remote_api.User) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, userImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -557,7 +557,7 @@ func (ec *executionContext) _User_likes(ctx context.Context, field graphql.Colle var viewerImplementors = []string{"Viewer"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Viewer(ctx context.Context, sel []query.Selection, obj *models.Viewer) graphql.Marshaler { +func (ec *executionContext) _Viewer(ctx context.Context, sel ast.SelectionSet, obj *models.Viewer) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, viewerImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -594,7 +594,7 @@ func (ec *executionContext) _Viewer_user(ctx context.Context, field graphql.Coll var __DirectiveImplementors = []string{"__Directive"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Directive(ctx context.Context, sel []query.Selection, obj *introspection.Directive) graphql.Marshaler { +func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __DirectiveImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -627,7 +627,7 @@ func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -638,11 +638,8 @@ func (ec *executionContext) ___Directive_description(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___Directive_locations(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) graphql.Marshaler { @@ -652,7 +649,7 @@ func (ec *executionContext) ___Directive_locations(ctx context.Context, field gr rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Locations() + res := obj.Locations arr1 := graphql.Array{} for idx1 := range res { arr1 = append(arr1, func() graphql.Marshaler { @@ -672,7 +669,7 @@ func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Args() + res := obj.Args arr1 := graphql.Array{} for idx1 := range res { arr1 = append(arr1, func() graphql.Marshaler { @@ -688,7 +685,7 @@ func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql var __EnumValueImplementors = []string{"__EnumValue"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___EnumValue(ctx context.Context, sel []query.Selection, obj *introspection.EnumValue) graphql.Marshaler { +func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __EnumValueImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -721,7 +718,7 @@ func (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -732,11 +729,8 @@ func (ec *executionContext) ___EnumValue_description(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) graphql.Marshaler { @@ -746,7 +740,7 @@ func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.IsDeprecated() + res := obj.IsDeprecated return graphql.MarshalBoolean(res) } @@ -757,17 +751,14 @@ func (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.DeprecationReason() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.DeprecationReason + return graphql.MarshalString(res) } var __FieldImplementors = []string{"__Field"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Field(ctx context.Context, sel []query.Selection, obj *introspection.Field) graphql.Marshaler { +func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __FieldImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -804,7 +795,7 @@ func (ec *executionContext) ___Field_name(ctx context.Context, field graphql.Col rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -815,11 +806,8 @@ func (ec *executionContext) ___Field_description(ctx context.Context, field grap rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) graphql.Marshaler { @@ -829,7 +817,7 @@ func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.Col rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Args() + res := obj.Args arr1 := graphql.Array{} for idx1 := range res { arr1 = append(arr1, func() graphql.Marshaler { @@ -849,8 +837,11 @@ func (ec *executionContext) ___Field_type(ctx context.Context, field graphql.Col rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Type() - return ec.___Type(ctx, field.Selections, &res) + res := obj.Type + if res == nil { + return graphql.Null + } + return ec.___Type(ctx, field.Selections, res) } func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) graphql.Marshaler { @@ -860,7 +851,7 @@ func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field gra rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.IsDeprecated() + res := obj.IsDeprecated return graphql.MarshalBoolean(res) } @@ -871,17 +862,14 @@ func (ec *executionContext) ___Field_deprecationReason(ctx context.Context, fiel rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.DeprecationReason() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.DeprecationReason + return graphql.MarshalString(res) } var __InputValueImplementors = []string{"__InputValue"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___InputValue(ctx context.Context, sel []query.Selection, obj *introspection.InputValue) graphql.Marshaler { +func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __InputValueImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -914,7 +902,7 @@ func (ec *executionContext) ___InputValue_name(ctx context.Context, field graphq rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Name() + res := obj.Name return graphql.MarshalString(res) } @@ -925,11 +913,8 @@ func (ec *executionContext) ___InputValue_description(ctx context.Context, field rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.Description + return graphql.MarshalString(res) } func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) graphql.Marshaler { @@ -939,8 +924,11 @@ func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphq rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.Type() - return ec.___Type(ctx, field.Selections, &res) + res := obj.Type + if res == nil { + return graphql.Null + } + return ec.___Type(ctx, field.Selections, res) } func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) graphql.Marshaler { @@ -950,17 +938,14 @@ func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, fiel rctx.Field = field rctx.PushField(field.Alias) defer rctx.Pop() - res := obj.DefaultValue() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + res := obj.DefaultValue + return graphql.MarshalString(res) } var __SchemaImplementors = []string{"__Schema"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Schema(ctx context.Context, sel []query.Selection, obj *introspection.Schema) graphql.Marshaler { +func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __SchemaImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -1016,7 +1001,10 @@ func (ec *executionContext) ___Schema_queryType(ctx context.Context, field graph rctx.PushField(field.Alias) defer rctx.Pop() res := obj.QueryType() - return ec.___Type(ctx, field.Selections, &res) + if res == nil { + return graphql.Null + } + return ec.___Type(ctx, field.Selections, res) } func (ec *executionContext) ___Schema_mutationType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) graphql.Marshaler { @@ -1070,7 +1058,7 @@ func (ec *executionContext) ___Schema_directives(ctx context.Context, field grap var __TypeImplementors = []string{"__Type"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) ___Type(ctx context.Context, sel []query.Selection, obj *introspection.Type) graphql.Marshaler { +func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler { fields := graphql.CollectFields(ec.Doc, sel, __TypeImplementors, ec.Variables) out := graphql.NewOrderedMap(len(fields)) @@ -1125,10 +1113,7 @@ func (ec *executionContext) ___Type_name(ctx context.Context, field graphql.Coll rctx.PushField(field.Alias) defer rctx.Pop() res := obj.Name() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + return graphql.MarshalString(res) } func (ec *executionContext) ___Type_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) graphql.Marshaler { @@ -1139,10 +1124,7 @@ func (ec *executionContext) ___Type_description(ctx context.Context, field graph rctx.PushField(field.Alias) defer rctx.Pop() res := obj.Description() - if res == nil { - return graphql.Null - } - return graphql.MarshalString(*res) + return graphql.MarshalString(res) } func (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) graphql.Marshaler { @@ -1333,14 +1315,10 @@ func (ec *executionContext) introspectSchema() *introspection.Schema { } func (ec *executionContext) introspectType(name string) *introspection.Type { - t := parsedSchema.Resolve(name) - if t == nil { - return nil - } - return introspection.WrapType(t) + return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]) } -var parsedSchema = schema.MustParse(`type Element { +var parsedSchema = gqlparser.MustLoadSchema(introspection.Prelude + `type Element { child: Element! error: Boolean! mismatched: [Boolean!] @@ -1380,5 +1358,5 @@ type Query { jsonEncoding: String! } -// this is a comment with a ` + "`" + `backtick` + "`" + ` +# this is a comment with a ` + "`" + `backtick` + "`" + ` `) diff --git a/test/models-go/generated.go b/test/models-go/generated.go index e9857e07792..cf97ab21f13 100644 --- a/test/models-go/generated.go +++ b/test/models-go/generated.go @@ -17,9 +17,6 @@ type DateFilter struct { type DateFilterOp string const ( - // multi - // line - // comment DateFilterOpEq DateFilterOp = "EQ" DateFilterOpNeq DateFilterOp = "NEQ" DateFilterOpGt DateFilterOp = "GT" diff --git a/test/resolvers_test.go b/test/resolvers_test.go index 7f4c04bf615..9cada0eb004 100644 --- a/test/resolvers_test.go +++ b/test/resolvers_test.go @@ -6,11 +6,10 @@ import ( "context" "fmt" "net/http/httptest" + "remote_api" "testing" "time" - "remote_api" - "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -18,16 +17,17 @@ import ( "github.com/vektah/gqlgen/graphql" "github.com/vektah/gqlgen/handler" "github.com/vektah/gqlgen/test/models-go" + "github.com/vektah/gqlparser/gqlerror" ) func TestCustomErrorPresenter(t *testing.T) { resolvers := &testResolvers{} srv := httptest.NewServer(handler.GraphQL(MakeExecutableSchema(resolvers), - handler.ErrorPresenter(func(i context.Context, e error) *graphql.Error { + handler.ErrorPresenter(func(i context.Context, e error) *gqlerror.Error { if _, ok := errors.Cause(e).(*specialErr); ok { - return &graphql.Error{Message: "override special error message"} + return &gqlerror.Error{Message: "override special error message"} } - return &graphql.Error{Message: e.Error()} + return &gqlerror.Error{Message: e.Error()} }), )) c := client.New(srv.URL) diff --git a/test/schema.graphql b/test/schema.graphql index 9bf2e99d8ff..42cbac39eb5 100644 --- a/test/schema.graphql +++ b/test/schema.graphql @@ -38,4 +38,4 @@ type Query { jsonEncoding: String! } -// this is a comment with a `backtick` +# this is a comment with a `backtick`