GithubHelp home page GithubHelp logo

gqlparser's People

Contributors

adwd avatar ahsanbarkati avatar atzedus avatar aurelijusbanelis avatar benjaminjkraft avatar code-hex avatar dependabot[bot] avatar duckbrain avatar edsrzf avatar emersion avatar fredzqm avatar giautm avatar jufemaiz avatar lwc avatar marwan-at-work avatar pawanrawal avatar philipaconrad avatar pjmd89 avatar ryicoh avatar schafle avatar singyue avatar stevenacoffman avatar tadeokondrak avatar vektah avatar vikstrous avatar vvakame avatar warashi avatar wilhelmeek avatar yuchenshi avatar zmay2030 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gqlparser's Issues

cannot use float64 as Int

Hello!

I have an input that contains a declared field called number, with an int value. sending a variable with the numerical value triggers the error
trigger:
validator.VariableValues
gqlparser version: 2.4.1
Details:

Error: 
*github.com/vektah/gqlparser/v2/gqlerror.Error {err: error nil, Message: "cannot use float64 as Int", Path: github.com/vektah/gqlparser/v2/ast.Path len: 3, cap: 4, [*(*"github.com/vektah/gqlparser/v2/ast.PathElement")(0xc000204a40),*(*"github.com/vektah/gqlparser/v2/ast.PathElement")(0xc000204a50),*(*"github.com/vektah/gqlparser/v2/ast.PathElement")(0xc000204a60)], Locations: []github.com/vektah/gqlparser/v2/gqlerror.Location len: 0, cap: 0, nil, Extensions: map[string]interface {} nil, Rule: ""}

github.com/vektah/gqlparser/v2/ast.Path len: 3, cap: 4, ["variable","vars","number"]

gql:

input insertData{
    name:String!
    data: data!
    lo:[String]!
    number:Int
}
input data{
    name: String
    value: String
}
type Query{
    readProviders(input: insertData):[Provider]
}
variable:
{"vars":  { "name": "valor de name", "data": {},"lo":["cadena 1","cadena 2"], "number":10 }}
Query:
query($vars:insertData){
  readProvidersx(input:$vars) {
    _id
    name
    rif
    address
    phone1
    phone2
    email
    nameLegal
    companyClass
    withholdingAgent
  }
}

gqlparser fails to parse `extend type` with a doc comment

If I have a type like this:

extend type Foo @key(fields: "id") {
  id: ID!
}

Then adding a doc comment will fail to parse.

Sample input:

"""
Doc comment
"""
extend type Foo @key(fields: "id") {
  id: ID!
}

Expected behavior: parses

Actual behavior:

failed to load schema:schema.graphqls:3: Unexpected BlockString "Doc comment"exit status 1

A possible workaround is available: the following code block parses correctly.

"""
Doc comment
"""
type Foo @key(fields: "id") @extends {
  id: ID!
}

Variable value validation allows String values for Int/Float variables and vice-versa

We observed that the VariableValues function of the validator and more specifically validateVarType allows to pass variable values of different types than expected in a few cases.

Examples

Example 1

When supplying a variable of type String, the value could be numeric.

mutation ($var: String) {
   doSomething(stringField: $var)
}

with variables

{
  "var": 1
}

Example 2

When supplying a variable of type Int/Float, the value could be a string.

mutation ($var: Int) {
   doSomething(intField $var)
}

with variables

{
  "var": "some string"
}

Is this behaviour intended?

The most important question here is whether this is intended to be the case, which could very well work if the final value is transformed in a later piece of logic. However, it seemed counterintuitive to allow type mismatch in a function that verifies that types do line up.

Source of the (potential) bug

As the scalar validation makes heavy use of reflection, based on the variable type declared in the operation, the validator checks against the kind of the provided value and makes sure that for a specific GraphQL scalar type only allows specific value kinds.

This one-sided check already becomes the problem in our case: As numeric values are unmarshalled to be json.Number values, which are stored as strings underneath, kind will evaluate to a string for numeric values.

In the validation case for String variables, numerics will pass the kind check in that way and won't get caught. This implies that we can add another check based on the actual type of the value, to make sure no json.Number is passed for a String variable. We introduced the following change for String scalar validation:

case "String":
  if kind == reflect.String {
    if val.Type().String() == "json.Number" {
      return gqlerror.ErrorPathf(v.path, "cannot use number as String")
    }

    return nil
  }

When validating the built-in numeric scalars (Int and Float), we naturally allow values with the kind String (for the reason that json.Number values are essentially Strings), but don't prevent "regular" String values from being supplied. For this case, we've added the following check:

case "String":
  if kind == reflect.String {
    if val.Type().String() == "json.Number" {
      return gqlerror.ErrorPathf(v.path, "cannot use number as String")
    }

    return nil
  }

Conclusion

Depending on the outcome of the question whether this is intended or not, I'd like to contribute a fix (could be the one above, or a different one with the same outcome).

Add Introspection Description to Scalar Types

Found that introspection returns empty descriptions for standard types. Not a big issue, but I found it curios why. Found that gqlparser/validator/prelude.graphql uses comments instead of description.

Currently:

# 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

Should be:

"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

See: https://facebook.github.io/graphql/June2018/#Description

What is __DirectiveResolver?

Hello,

Just by updating from v2.1.0 to v2.2.0 I noticed in my generated code I have now a new resolver:

__DirectiveResolver

I guess it's linked to: graphql/graphql-spec#510

I don't now if it's a bug, or if I have to implement something :)

type ResolverRoot interface {
       // ...
	__Directive() __DirectiveResolver
}


type __DirectiveResolver interface {
	IsRepeatable(ctx context.Context, obj *introspection.Directive) (bool, error)
}

[Bug] - Variable can't work when included __typename

Issue Example:

```{"operationName":null,"variables":{"storeID":2018,"data":{"name":"Demo","uuid":null,"treeDisplayType":"TREE","modelTree":[{"type":"NORMAL","level":1,"__typename":"ModuleModelTree"},{"level":2,"type":"NORMAL"},{"level":3,"type":"NORMAL"},{"level":4,"type":"NORMAL"},{"level":5,"type":"NORMAL"}],"modelID":250}},"query":"mutation ($storeID: Int, $data: UpdateModuleModelInput!) {
  updateModuleModel(storeID: $storeID, input: $data) {
    id
    name
    type
    uuid
    storeID
    treeDisplayType
    modelTree {
      level
      type
      __typename
    }
    __typename
  }
}
"}

How to Fix:

maybe we need skip __typename on variable validation.

Tag a new release

We're excited to start using #148 among other things. If a maintainer has time, would it be possible to tag a new release? (Or if there's anything others can do to help make that easier, I or my coworkers may have some time to help.)

Question: Can we cut new release for gqlgen to use?

Right now the gqlparser v2.2.0 has a bug that has been fixed in master. This fix will let the deprecated directive to work in gqlgen. Wondering if there is anything we can do to cut a new version so gqlgen can update gqlparser version with fix?

Are DirectiveLocations not checked in validation?

The following code doesn't give any errors, while it should have:

package main

import (
	"fmt"

	"github.com/vektah/gqlparser/v2/ast"
	"github.com/vektah/gqlparser/v2/parser"
	"github.com/vektah/gqlparser/v2/validator"
)

func main() {
	schema := `
directive @test on OBJECT
type T1 @test {
	f: String
}
type T2 {
	f: String
}
union U @test = T1 | T2
input I1 @test {
	f: String
}
interface I2 @test {
	f: String
}
`
	doc, err := parser.ParseSchemas(validator.Prelude, &ast.Source{Input: schema})
	if err != nil {
		panic(err)
	}

	_, err = validator.ValidateSchemaDocument(doc)
	if err != nil {
		panic(err)
	}
	fmt.Println("Oops! got a bug :(")
}

The directive @test is defined to be applicable only on an OBJECT type, but it doesn't give any error when applied on union, input, interface, or any other types.

Try it on The Go Playground.

Maybe related to #107?

Distribute prelude string over multiple lines

Having one big long string literal in validator/prelude.go is a bit problematic. Foremostly it makes it hard to see what changes have been made in git history or blame. (I was trying to check if/when description: String field has been added to type __Schema.)

Is there any reason not to have it extend over multiple lines? (String literals joined with the + operator are combined into one literal at compile time, I believe.)

Perhaps even better would be to embed it (//go:embed), since go.mod is already at Go 1.16. (File embedding was added in 1.16.)

Use error instead of *gqlerror.Error

In gqlparser all methods which are returning an error are using the explicit struct type (e.g. *gqlerror.Error or gqlerror.List).

Problem

As long as you use the explicit types everything is fine, but as soon as you convert them to the error interface type, nil checks will fail.

See the golang FAQ for information why the checks fail.
https://golang.org/doc/faq#nil_error

Example

read.go

func ReadSchema(dir string) (*ast.Schema, error) {
  var files []*ast.Source

  // ... read files, may return io errors ...

  // Here the returned *gqlerror.Error gets converted to the error return type.
  return gqlparser.LoadSchema(files...)
}

The ReadSchema function may return io errors and graphql errors. Because of this I can't use *gqlerror.Error as return type. When testing this I noticed that my nil checks failed.

read_test.go

func TestReadSchema(t *testing.T) {
  schema, err := readSchema(schemaTestDir)

  // This check always fails
  assert.Assert(t, err == nil)

  // A workaround is to convert the error back to its struct type.
  // When handling multiple error types this quickly becomes impractical.
  assert.Assert(t, err.(*gqlerror.Error) == nil)
}

It's kind of strange that gqlparser returns errors as struct types. I've never seen anywhere else. All other go packages (including the internal ones) use the error interface type.

I think this should be changed so all methods use the error interface when returning errors.

ast.Field#Definition is nil unexpectedly in Fragment walking

I'm trying to implement OverlappingFieldsCanBeMerged validator in here.
but I got some issues.

  • I got ast.Field#Definition is nil in Fragment walking.
    • Fragment visitor fires before the walker sets the value of Definition ๐Ÿ˜ฟ
  • I tried to implement observers.OnFragmentLeave, but walkSelection(parentDef *ast.Definition, it ast.Selection) and any other walker method using call by value.
    • golang's CodeReviewComments
    • I think we should use much more pointer!
      • I do not think that it is common to make call by value to represent non-nil
    • but maybe this is hard work... e.g...
      • type SelectionSet []Selection โ†’ type SelectionSet []*Selection
      • func (Field) isSelection() {} โ†’ func (*Field) isSelection() {}

As a reasonable solution, I think that setting all the definitions before calling visitor. ๐Ÿค”
However, I recommend using more pointers.

Facing issue `can not find package github.com/vektah/gqlparser/v2/ast`

We have been using gqlgen-v0.9.2 since a year, and now we are updating it to latest version. Straight forward I updated all the dependencies. But still after 2 days of efforts, I am getting errors.

Getting error message
vendor/github.com/99designs/gqlgen/graphql/context_field.go:7:2: cannot find package "github.com/vektah/gqlparser/v2/ast" in any of:

gqlgen version: 0.12.2

Wrong validation of not null field with default value on inputs

I have the following mutation:

extend type Mutation{
  createProject(clientMutationId: String, input: ProjectDraft!): ProjectOperationResponse!
}

input ProjectDraft {
  test: Boolean! = true
  name: String!
}

When I call it with the query:

mutation($projectDraft: ProjectDraft!) {
    createProject(input: $projectDraft) {
     ...
    }
}

And the variables:

{
	"projectDraft": {
		"name": "Toto"
	}
}

=> I receive the must be defined error on the field test, even if there is a default value (true).

But I don't get any error when I call my mutation without variables:

mutation($projectDraft: ProjectDraft!) {
    createProject(input: {name: "toto"}) {
     ...
    }
}

It appears that the default values โ€‹โ€‹of the input field definitions are not checked to determine whether a not null field is valid or not.

fatal error: stack overflow in case of incorrect recursive request

Hi. have found endless recursion in case of incorrect graphql request. is there a way to prohibit that?

request:

query Streams {
  Streams {
    ...StreamFragment
  }
}

fragment StreamFragment on Stream {
  ID
  Streams {
    ...StreamFragment
    Streams {
      ...StreamFragment
      Streams {
        ...StreamFragment
      }
    }
  }
}

schema:

type Stream 
    ID: ID!
    Streams:          [Stream]
}

stack trace

runtime: goroutine stack exceeds 1000000000-byte limit
runtime: sp=0xc033200400 stack=[0xc033200000, 0xc053200000]
fatal error: stack overflow
runtime stack:
runtime.throw({0xddc55b, 0x147ad20})
        /usr/local/go/src/runtime/panic.go:1198 +0x71
runtime.newstack()
        /usr/local/go/src/runtime/stack.go:1088 +0x5ac
runtime.morestack()
        /usr/local/go/src/runtime/asm_amd64.s:461 +0x8b
goroutine 8 [running]:
runtime.heapBitsSetType(0xc05358ee50, 0x10, 0x10, 0xcb1b20)
        /usr/local/go/src/runtime/mbitmap.go:822 +0xbcc fp=0xc033200410 sp=0xc033200408 pc=0x415a0c
runtime.mallocgc(0x10, 0xcb1b20, 0x1)
        /usr/local/go/src/runtime/malloc.go:1100 +0x65e fp=0xc033200490 sp=0xc033200410 pc=0x40ccbe
runtime.growslice(0xcb1b20, {0x0, 0xc000020bc9, 0x2}, 0x30)
        /usr/local/go/src/runtime/slice.go:267 +0x4ea fp=0xc0332004f8 sp=0xc033200490 pc=0x44b1aa
github.com/vektah/gqlparser/v2/validator/rules.(*sequentialFieldsMap).Push(...)
        /go/pkg/mod/github.com/vektah/gqlparser/[email protected]/validator/rules/overlapping_fields_can_be_merged.go:160
github.com/vektah/gqlparser/v2/validator/rules.getFieldsAndFragmentNames.func1({0xc00038adc0, 0x3, 0xd51740})
        /go/pkg/mod/github.com/vektah/gqlparser/[email protected]/validator/rules/overlapping_fields_can_be_merged.go:544 +0x165 fp=0xc0332005b0 sp=0xc0332004f8 pc=0xbbd5c5
github.com/vektah/gqlparser/v2/validator/rules.getFieldsAndFragmentNames({0xc00038adc0, 0x3, 0x4})
        /go/pkg/mod/github.com/vektah/gqlparser/[email protected]/validator/rules/overlapping_fields_can_be_merged.go:554 +0xea fp=0xc033200620 sp=0xc0332005b0 pc=0xbbd40a
github.com/vektah/gqlparser/v2/validator/rules.(*overlappingFieldsCanBeMergedManager).collectConflictsBetweenFieldsAndFragment(0xc0001ab038, 0xc05a8d8678, 0x2, 0x100000000000000, 0xc00038ac>
        /go/pkg/mod/github.com/vektah/gqlparser/[email protected]/validator/rules/overlapping_fields_can_be_merged.go:282 +0xaa fp=0xc033200698 sp=0xc033200620 pc=0xbbbd2a
github.com/vektah/gqlparser/v2/validator/rules.(*overlappingFieldsCanBeMergedManager).findConflictsBetweenSubSelectionSets(0xc0001ab038, 0x0, {0xc000386c60, 0x1, 0x1}, {0xc00006a220, 0x2, 0>
        /go/pkg/mod/github.com/vektah/gqlparser/[email protected]/validator/rules/overlapping_fields_can_be_merged.go:360 +0x125 fp=0xc033200738 sp=0xc033200698 pc=0xbbc2c5
github.com/vektah/gqlparser/v2/validator/rules.(*overlappingFieldsCanBeMergedManager).findConflict(0xc0001ab038, 0xfe, 0xc000205e80, 0xc000205e00)
        /go/pkg/mod/github.com/vektah/gqlparser/[email protected]/validator/rules/overlapping_fields_can_be_merged.go:465 +0x4b5 fp=0xc0332007e8 sp=0xc033200738 pc=0xbbce15
github.com/vektah/gqlparser/v2/validator/rules.(*overlappingFieldsCanBeMergedManager).collectConflictsBetween(0xc00006a260, 0xc05a8d8660, 0x2, 0x10000000048a9ba, 0xc026dcdb80)
        /go/pkg/mod/github.com/vektah/gqlparser/[email protected]/validator/rules/overlapping_fields_can_be_merged.go:407 +0x179 fp=0xc0332008a8 sp=0xc0332007e8 pc=0xbbc879
github.com/vektah/gqlparser/v2/validator/rules.(*overlappingFieldsCanBeMergedManager).findConflictsBetweenSubSelectionSets(0xc0001ab038, 0x0, {0xc00006a220, 0x2, 0x2}, {0xc00006a260, 0x2, 0>
        /go/pkg/mod/github.com/vektah/gqlparser/[email protected]/validator/rules/overlapping_fields_can_be_merged.go:354 +0xfd fp=0xc033200948 sp=0xc0332008a8 pc=0xbbc29d
github.com/vektah/gqlparser/v2/validator/rules.(*overlappingFieldsCanBeMergedManager).findConflict(0xc0001ab038, 0x0, 0xc000205e00, 0xc000205d80)
        /go/pkg/mod/github.com/vektah/gqlparser/[email protected]/validator/rules/overlapping_fields_can_be_merged.go:465 +0x4b5 fp=0xc0332009f8 sp=0xc033200948 pc=0xbbce15
github.com/vektah/gqlparser/v2/validator/rules.(*overlappingFieldsCanBeMergedManager).collectConflictsBetween(0xd1d720, 0xc05a8d8648, 0x20, 0xc026dcdac0, 0xc026dcdac0)
        /go/pkg/mod/github.com/vektah/gqlparser/[email protected]/validator/rules/overlapping_fields_can_be_merged.go:407 +0x179 fp=0xc033200ab8 sp=0xc0332009f8 pc=0xbbc879
github.com/vektah/gqlparser/v2/validator/rules.(*overlappingFieldsCanBeMergedManager).collectConflictsBetweenFieldsAndFragment(0xc0001ab038, 0xc05a8d8648, 0x2, 0x10000000048a9ba, 0xc00038ad>
        /go/pkg/mod/github.com/vektah/gqlparser/[email protected]/validator/rules/overlapping_fields_can_be_merged.go:291 +0xf2 fp=0xc033200b30 sp=0xc033200ab8 pc=0xbbbd72
github.com/vektah/gqlparser/v2/validator/rules.(*overlappingFieldsCanBeMergedManager).findConflictsBetweenSubSelectionSets(0xc0001ab038, 0x0, {0xc000386c60, 0x1, 0x1}, {0xc00006a260, 0x2, 0>
        /go/pkg/mod/github.com/vektah/gqlparser/[email protected]/validator/rules/overlapping_fields_can_be_merged.go:367 +0x197 fp=0xc033200bd0 sp=0xc033200b30 pc=0xbbc337
github.com/vektah/gqlparser/v2/validator/rules.(*overlappingFieldsCanBeMergedManager).findConflict(0xc0001ab038, 0x0, 0xc000205e80, 0xc000205d80)
        /go/pkg/mod/github.com/vektah/gqlparser/[email protected]/validator/rules/overlapping_fields_can_be_merged.go:465 +0x4b5 fp=0xc033200c80 sp=0xc033200bd0 pc=0xbbce15
github.com/vektah/gqlparser/v2/validator/rules.(*overlappingFieldsCanBeMergedManager).collectConflictsBetween(0xd1d720, 0xc05a8d8630, 0x20, 0xc026dcd9a0, 0xc026dcd9a0)
        /go/pkg/mod/github.com/vektah/gqlparser/[email protected]/validator/rules/overlapping_fields_can_be_merged.go:407 +0x179 fp=0xc033200d40 sp=0xc033200c80 pc=0xbbc879
github.com/vektah/gqlparser/v2/validator/rules.(*overlappingFieldsCanBeMergedManager).collectConflictsBetweenFieldsAndFragment(0xc0001ab038, 0xc05a8d8630, 0x2, 0x100000000000000, 0xc00038ad>
        /go/pkg/mod/github.com/vektah/gqlparser/[email protected]/validator/rules/overlapping_fields_can_be_merged.go:291 +0xf2 fp=0xc033200db8 sp=0xc033200d40 pc=0xbbbd72
github.com/vektah/gqlparser/v2/validator/rules.(*overlappingFieldsCanBeMergedManager).findConflictsBetweenSubSelectionSets(0xc0001ab038, 0x0, {0xc000386c60, 0x1, 0x1}, {0xc00006a220, 0x2, 0>
        /go/pkg/mod/github.com/vektah/gqlparser/[email protected]/validator/rules/overlapping_fields_can_be_merged.go:367 +0x197 fp=0xc033200e58 sp=0xc033200db8 pc=0xbbc337
github.com/vektah/gqlparser/v2/validator/rules.(*overlappingFieldsCanBeMergedManager).findConflict(0xc0001ab038, 0xfe, 0xc000205e80, 0xc000205e00)
        /go/pkg/mod/github.com/vektah/gqlparser/[email protected]/validator/rules/overlapping_fields_can_be_merged.go:465 +0x4b5 fp=0xc033200f08 sp=0xc033200e58 pc=0xbbce15

schema.graphql:8: Directive possibleTypes is not applicable on FIELD_DEFINITION.

The error has caused on master branch (7e475a7)

I used gqlparser.LoadSchema and use GitHub public schema to reproduce this error. expected INPUT_FIELD_DEFINITION

directive @possibleTypes(
  abstractType: String
  concreteTypes: [String!]!
) on INPUT_FIELD_DEFINITION

input AcceptEnterpriseAdministratorInvitationInput {
  clientMutationId: String
  invitationId: ID! @possibleTypes(concreteTypes: ["EnterpriseAdministratorInvitation"])
}

type Query {
  id: ID!
}

type Mutation {
  hello(input: AcceptEnterpriseAdministratorInvitationInput): ID!
}

Validation for custom scalar types.

We have a custom scalar type and want to add input validation for it.
As of now, there is no hook provided for it. We have to either fork and modify the library or write the validation in our own code.
It would be better if we can add custom validation rules as we do for events like on operation, onField, etc in walk.go.

Unexpected panic when parsing query.

Expected Behaviour

receive an graphQLError result object

Actual Behavior

panic is thrown.

http: panic serving [::1]:64085: runtime error: invalid memory address or nil pointer dereference
goroutine 4285 [running]:
net/http.(*conn).serve.func1(0xc4206c8000)
        /usr/local/Cellar/go/1.10.3/libexec/src/net/http/server.go:1726 +0xd0
panic(0x1607600, 0x1beac80)
        /usr/local/Cellar/go/1.10.3/libexec/src/runtime/panic.go:502 +0x229
github.rakops.com/prospecting/prospr-api/vendor/github.com/vektah/gqlparser/validator/rules.(*overlappingFieldsCanBeMergedManager).findConflict(0xc420468300, 0xc42088ea00, 0xc4202a8300, 0xc4202a8400, 0xc4200e8608)
        /Users/jonlundy/Documents/go/src/github.rakops.com/prospecting/prospr-api/vendor/github.com/vektah/gqlparser/validator/rules/overlapping_fields_can_be_merged.go:419 +0x73a
github.rakops.com/prospecting/prospr-api/vendor/github.com/vektah/gqlparser/validator/rules.(*overlappingFieldsCanBeMergedManager).collectConflictsBetween(0xc420468300, 0xc420aa9528, 0x1628e00, 0xc420468660, 0xc4204686e0)
        /Users/jonlundy/Documents/go/src/github.rakops.com/prospecting/prospr-api/vendor/github.com/vektah/gqlparser/validator/rules/overlapping_fields_can_be_merged.go:403 +0xc4
github.rakops.com/prospecting/prospr-api/vendor/github.com/vektah/gqlparser/validator/rules.(*overlappingFieldsCanBeMergedManager).collectConflictsBetweenFieldsAndFragment(0xc420468300, 0xc420aa9528, 0xc420468600, 0xc420468660, 0xc420520980)
        /Users/jonlundy/Documents/go/src/github.rakops.com/prospecting/prospr-api/vendor/github.com/vektah/gqlparser/validator/rules/overlapping_fields_can_be_merged.go:291 +0x160
github.rakops.com/prospecting/prospr-api/vendor/github.com/vektah/gqlparser/validator/rules.(*overlappingFieldsCanBeMergedManager).findConflictsWithinSelectionSet(0xc420468300, 0xc420468220, 0x2, 0x2, 0xc42088e3f0, 0xc420a50050, 0xc42088ea20)
        /Users/jonlundy/Documents/go/src/github.rakops.com/prospecting/prospr-api/vendor/github.com/vektah/gqlparser/validator/rules/overlapping_fields_can_be_merged.go:258 +0x1b2
github.rakops.com/prospecting/prospr-api/vendor/github.com/vektah/gqlparser/validator/rules.init.11.func1.2(0xc420520bc0, 0xc4202a8280)
        /Users/jonlundy/Documents/go/src/github.rakops.com/prospecting/prospr-api/vendor/github.com/vektah/gqlparser/validator/rules/overlapping_fields_can_be_merged.go:87 +0x7c
github.rakops.com/prospecting/prospr-api/vendor/github.com/vektah/gqlparser/validator.(*Walker).walkSelection(0xc420520bc0, 0xc4201bc8f0, 0x172ee40, 0xc4202a8280)
        /Users/jonlundy/Documents/go/src/github.rakops.com/prospecting/prospr-api/vendor/github.com/vektah/gqlparser/validator/walk.go:243 +0x26a
github.rakops.com/prospecting/prospr-api/vendor/github.com/vektah/gqlparser/validator.(*Walker).walkSelectionSet(0xc420520bc0, 0xc4201bc8f0, 0xc4207af620, 0x1, 0x1)
        /Users/jonlundy/Documents/go/src/github.rakops.com/prospecting/prospr-api/vendor/github.com/vektah/gqlparser/validator/walk.go:205 +0x59
github.rakops.com/prospecting/prospr-api/vendor/github.com/vektah/gqlparser/validator.(*Walker).walkOperation(0xc420520bc0, 0xc42066a3f0)
        /Users/jonlundy/Documents/go/src/github.rakops.com/prospecting/prospr-api/vendor/github.com/vektah/gqlparser/validator/walk.go:110 +0x2d7
github.rakops.com/prospecting/prospr-api/vendor/github.com/vektah/gqlparser/validator.(*Walker).walk(0xc420520bc0)
        /Users/jonlundy/Documents/go/src/github.rakops.com/prospecting/prospr-api/vendor/github.com/vektah/gqlparser/validator/walk.go:69 +0x52
github.rakops.com/prospecting/prospr-api/vendor/github.com/vektah/gqlparser/validator.Walk(0xc4201cdec0, 0xc420520840, 0xc42035e0c0)
        /Users/jonlundy/Documents/go/src/github.rakops.com/prospecting/prospr-api/vendor/github.com/vektah/gqlparser/validator/walk.go:53 +0xa6
github.rakops.com/prospecting/prospr-api/vendor/github.com/vektah/gqlparser/validator.Validate(0xc4201cdec0, 0xc420520840, 0x0, 0x16bd5aa, 0xc)
        /Users/jonlundy/Documents/go/src/github.rakops.com/prospecting/prospr-api/vendor/github.com/vektah/gqlparser/validator/validator.go:42 +0x181
github.rakops.com/prospecting/prospr-api/vendor/github.com/vektah/gqlparser.LoadQuery(0xc4201cdec0, 0xc4206ad880, 0x314, 0x16c00e2, 0x10, 0x0, 0x168b9c0)
        /Users/jonlundy/Documents/go/src/github.rakops.com/prospecting/prospr-api/vendor/github.com/vektah/gqlparser/gqlparser.go:28 +0xe7
github.rakops.com/prospecting/prospr-api/vendor/github.com/99designs/gqlgen/handler.GraphQL.func1(0x1731c80, 0xc420232460, 0xc420136700)
        /Users/jonlundy/Documents/go/src/github.rakops.com/prospecting/prospr-api/vendor/github.com/99designs/gqlgen/handler/graphql.go:160 +0x267
net/http.HandlerFunc.ServeHTTP(0xc4204681c0, 0x1731c80, 0xc420232460, 0xc420136700)
        /usr/local/Cellar/go/1.10.3/libexec/src/net/http/server.go:1947 +0x44
net/http.StripPrefix.func1(0x1731c80, 0xc420232460, 0xc420136600)
        /usr/local/Cellar/go/1.10.3/libexec/src/net/http/server.go:1986 +0x19a
net/http.HandlerFunc.ServeHTTP(0xc42088e360, 0x1731c80, 0xc420232460, 0xc420136600)
        /usr/local/Cellar/go/1.10.3/libexec/src/net/http/server.go:1947 +0x44
github.rakops.com/prospecting/prospr-api/internal/routes.getQuery(0x1731c80, 0xc420232460, 0xc420520500, 0xc420136600, 0x1734860, 0xc42088e300)
        /Users/jonlundy/Documents/go/src/github.rakops.com/prospecting/prospr-api/internal/routes/graphql.go:37 +0x1cc
github.rakops.com/prospecting/prospr-api/vendor/sour.is/x/toolbox/httpsrv.HandlerFunc.ServeHTTP(0x16e2bc8, 0x1731c80, 0xc420232460, 0xc420520500, 0xc420136500, 0x1734860, 0xc42088e300)
        /Users/jonlundy/Documents/go/src/github.rakops.com/prospecting/prospr-api/vendor/sour.is/x/toolbox/httpsrv/routes_ident.go:33 +0x173
github.rakops.com/prospecting/prospr-api/vendor/sour.is/x/toolbox/httpsrv.identWrapper.func1(0x1731c80, 0xc420232460, 0xc420136500)
        /Users/jonlundy/Documents/go/src/github.rakops.com/prospecting/prospr-api/vendor/sour.is/x/toolbox/httpsrv/wrappers.go:23 +0x484
net/http.HandlerFunc.ServeHTTP(0xc4203009a0, 0x1731c80, 0xc420232460, 0xc420136500)
        /usr/local/Cellar/go/1.10.3/libexec/src/net/http/server.go:1947 +0x44
github.rakops.com/prospecting/prospr-api/vendor/github.com/gorilla/mux.(*Router).ServeHTTP(0xc42020ecb0, 0x1731c80, 0xc420232460, 0xc420136500)
        /Users/jonlundy/Documents/go/src/github.rakops.com/prospecting/prospr-api/vendor/github.com/gorilla/mux/mux.go:162 +0xed
net/http.serverHandler.ServeHTTP(0xc4202091e0, 0x1731c80, 0xc420232460, 0xc420596100)
        /usr/local/Cellar/go/1.10.3/libexec/src/net/http/server.go:2694 +0xbc
net/http.(*conn).serve(0xc4206c8000, 0x1732180, 0xc4201c6040)
        /usr/local/Cellar/go/1.10.3/libexec/src/net/http/server.go:1830 +0x651
created by net/http.(*Server).Serve
        /usr/local/Cellar/go/1.10.3/libexec/src/net/http/server.go:2795 +0x27b

Minimal graphql.schema and models to reproduce

query panic{
  panic{  
    ...PanicInput
    __typename
  }
}
fragment PanicInput on Panic {
  __typename
}

This was filed over under 99designs/gqlgen#290 but probably fits here better as it originates from the parser.

Bazel build fails

Hello,

I use Bazel Gazelle to generate BUILD files. It seems Bazel cannot load vektah gqlparser. But I don't have no more ideas how to look into this issue. Maybe the repository isn't compatible because of this "v2" sub folder?

no such package '@com_github_vektah_gqlparser_v2//ast': The repository '@com_github_vektah_gqlparser_v2' could not be resolved and referenced by '//src/graph/generated:generated'

Thank you for your help!

go.mod

require (
	github.com/99designs/gqlgen v0.13.0 // indirect
	github.com/vektah/gqlparser/v2 v2.1.0 // indirect
)

Generated bazel BUILD file in graph/generated

load("@io_bazel_rules_go//go:def.bzl", "go_library")

go_library(
    name = "generated",
    srcs = ["generated.go"],
    importpath = "src/graph/generated",
    visibility = ["//visibility:public"],
    deps = [
        "//src/graph/model",
        "@com_github_99designs_gqlgen//graphql:go_default_library",
        "@com_github_99designs_gqlgen//graphql/introspection:go_default_library",
        "@com_github_vektah_gqlparser_v2//:go_default_library",
        "@com_github_vektah_gqlparser_v2//ast:go_default_library",
    ],
)

update tests from graphql-js

Looks like the tests exported from the graphql-js repo are very out of date. I looked through the history of the graphql-js repo and it looks like the package.json in validator/imported/package.json file comes from https://github.com/graphql/graphql-js/blob/68577079930e24da9c25b6c3f8fcadd488d94014/package.json. Trying to update the tests with ./export.sh doesn't work any more. The first problem seems related to babel, but there might be a lot more broken things here. I'm curious to know how much the two repos have diverged, so I'd like to get these tests updated. Any tips would be appreciated.

Extensions with Code field

apollo-client & apollo-server has a new feature that recognize error code by reading extensions.code from graphql error response. Also, in graphql spec, it allows extensions with code field. Current gqlerror only allows to set file as a field of extension map. Can we set any arbitrary field on it?

AST String method

Would like a method to generate the string representation of an AST object that could be directly used in a query. For example, if had a Field that was generated from

object(id:$id){ id name value subobject(index:9){ id name }}

would like to be able to call something like

ast.String(field)

to return an equivalent string.

I wrote a utility function to do this in my own project, but it is specific to ast.Field and doubt it covers all possible definitions:

func fieldQueryString(field *ast.Field) string {
	query := field.Name
	if len(field.Arguments) > 0 {
		query += "("
		for _, arg := range field.Arguments {
			query += arg.Name + ":"
			query += field.Arguments.ForName(arg.Name).Value.String()
		}
		query += ")"
	}
	if len(field.SelectionSet) > 0 {
		query += "{"
		for _, f := range field.SelectionSet {
			field := f.(*ast.Field)
			query += fieldQueryString(field) + ","
		}
		query += "}"
	}

	return query
}

I think this would be generally useful for logging/debugging.

Apologies if this already exists, please point to where it is found if exists.

Adding nullable field to vars.graphql InputType breaks tests

I am new to graphql but I think adding a nullable embedded input type should not break the tests since it is nullable and not required but instead it is checking for the required fields inside the nullable input type.

// vars.graphql

type Query {
  optionalIntArg(i: Int): Boolean!
  intArg(i: Int!): Boolean!
  stringArg(i: String): Boolean!
  boolArg(i: Boolean!): Boolean!
  floatArg(i: Float!): Boolean!
  idArg(i: ID!): Boolean!
  scalarArg(i: Custom!): Boolean!
  structArg(i: InputType!): Boolean!
  defaultStructArg(i: InputType! = { name: "foo" }): Boolean!
  arrayArg(i: [InputType!]): Boolean!
}

input InputType {
  embedded: Embedded
  name: String!
  nullName: String
}

input Embedded {
  name: String!
}

scalar Custom
--- FAIL: TestValidateVars (0.00s)
    --- FAIL: TestValidateVars/input_object (0.00s)
        --- FAIL: TestValidateVars/input_object/null_required_field (0.00s)
            /Users/cbelsole/go/src/github.com/vektah/gqlparser/validator/vars_test.go:103: 
                	Error Trace:	vars_test.go:103
                	Error:      	Error message not equal:
                	            	expected: "input: variable.var.name cannot be null"
                	            	actual  : "input: variable.var.embedded.name cannot be null"
                	Test:       	TestValidateVars/input_object/null_required_field

Nested field arguments don't seem to be used for conflict validation

Hi there,

this might be related to #107 but I figured it would be better to open a new issue as it's related to field arguments.

The following query will raise an error as expected:

{
  country(code: "DE") {
    name
  }
  country(code: "US") {
    name
  }
}

panic: input:6: Fields "country" conflict because they have differing arguments. Use different aliases on the fields to fetch both if this was intentional.

Whereas the same query with nested arguments will not:

{
  countryWhere(where: {code: "DE"}) {
    name
  }
  countryWhere(where: {code: "US"}) {
    name
  }
}

Full test case:

package main

import (
	"fmt"

	"github.com/vektah/gqlparser"
	"github.com/vektah/gqlparser/ast"
)

func main() {
	typedef := `
		type Country {
			name: String
		}

		type Query {
			country(code: String): Country
			countryWhere(where: CountryWhereUniqueInput!): Country
		}

		input CountryWhereUniqueInput {
			code: String
		}
	`
	// query := `
	// 	{
	// 		country(code: "DE") {
	// 			name
	// 		}
	// 		country(code: "US") {
	// 			name
	// 		}
	// 	}
	// `
	query := `
		{
			countryWhere(where: {code: "DE"}) {
				name
			}
			countryWhere(where: {code: "US"}) {
				name
			}
		}
	`

	schema, schemaErr := gqlparser.LoadSchema(&ast.Source{
		Input: typedef,
	})
	if schemaErr != nil {
		panic(schemaErr)
	}

	doc, queryErr := gqlparser.LoadQuery(schema, query)
	if queryErr != nil {
		panic(queryErr)
	}

	fmt.Println(schema, doc)
}

Is this issue of the same origin as #107 or a different beast?

Thanks for the all the great work with gqlparser!

Resolver's default values ignored when querying without setting variables

schema.graphql

  type Query {
    x (y: Int = 100): Int
  }

When requesting query without setting variables,

query ($y: Int) {
  x(y: $y)
}

# curl 'http://localhost:4000/' -H 'content-type: application/json' --data-binary '{"operationName":null,"variables":{},"query":"query ($y: Int) {\n  x(y: $y)\n}\n"}' --compressed

y should be set as 100 (default value), but actually it was set as 0.

I am not sure that it is specified in the official spec, but the gqlgen's old parser and apollo set it to 100.

invalid memory address or nil pointer dereference calling `arg2map` with `f.Definition` `nil`!

Upgrading from github.com/vektah/gqlparser/v2 v2.1.0 to github.com/vektah/gqlparser/v2 v2.2.0 with the same generated ([email protected]) code and all the same files I get a monster error:

runtime error: invalid memory address or nil pointer dereference.

After a long time of debugging I realized the problem is here:

func (f *Field) ArgumentMap(vars map[string]interface{}) map[string]interface{} {
	return arg2map(f.Definition.Arguments, f.Arguments, vars)
}

f.Definition here is nil with v2.2.0, not with 2.1.0! Why?

How to fix this?

How to get each sub queries?

query is

source := `{
	a:list(size: 2) {
		list(size: 5) {
			list(size: 15) {
				scalar
			}
		}
	}
	b:list(size: 6) {
		list(size: 3) {
			scalar
		}
	}
}`

query := gqlparser.MustLoadQuery(schema, source)

for _, selection := range query.Operations[0].SelectionSet {
}

Any way to get sub query a and b separately in the for range loop?

Package formatter is not available with Go modules

Using Go 1.13 and Go modules, looks like the package formatter is not available, and in effect it's not available in the tagged v1.1.2. I don't know whether or not it supposed to be this way, but for coherence, maybe it's worth to cut another release that would include the formatter, so that the behavior is the same when using GOPATH mode and Go modules.

possible recursion bug

typ.Elem = p.parseTypeReference()

Note that this line calls the function we are in, parseTypeReference. I'll try to

I am getting a great many errors like this as I try to write a schema. I cant seem to construct a small test case, but if I find one I'll update this ticket.

$ gqlgen init
runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow

runtime stack:
runtime.throw(0x13409f2, 0xe)
	/Users/iansmith/go1.10.3.src/go/src/runtime/panic.go:616 +0x81
runtime.newstack()
	/Users/iansmith/go1.10.3.src/go/src/runtime/stack.go:1054 +0x71f
runtime.morestack()
	/Users/iansmith/go1.10.3.src/go/src/runtime/asm_amd64.s:480 +0x89

goroutine 1 [running]:
runtime.heapBitsSetType(0xc42eef6db0, 0x30, 0x28, 0x1308b40)
	/Users/iansmith/go1.10.3.src/go/src/runtime/mbitmap.go:864 +0x61c fp=0xc440200358 sp=0xc440200350 pc=0x10128bc
runtime.mallocgc(0x30, 0x1308b40, 0x1, 0x0)
	/Users/iansmith/go1.10.3.src/go/src/runtime/malloc.go:740 +0x548 fp=0xc4402003f8 sp=0xc440200358 pc=0x100f928
runtime.newobject(0x1308b40, 0x2d)
	/Users/iansmith/go1.10.3.src/go/src/runtime/malloc.go:839 +0x38 fp=0xc440200428 sp=0xc4402003f8 pc=0x100ff28
github.com/vektah/gqlparser/parser.(*parser).parseTypeReference(0xc4201a7c70, 0x0)
	/Users/iansmith/graphql.src/graphiql/src/github.com/vektah/gqlparser/parser/query.go:312 +0x31 fp=0xc440200490 sp=0xc440200428 pc=0x1213051

...

github.com/vektah/gqlparser/parser.(*parser).parseTypeReference(0xc4201a7c70, 0x0)
	/Users/iansmith/graphql.src/graphiql/src/github.com/vektah/gqlparser/parser/query.go:316 +0x9b fp=0xc440202b28 sp=0xc440202ac0 pc=0x12130bb
github.com/vektah/gqlparser/parser.(*parser).parseTypeReference(0xc4201a7c70, 0x0)
	/Users/iansmith/graphql.src/graphiql/src/github.com/vektah/gqlparser/parser/query.go:316 +0x9b fp=0xc440202b90 sp=0xc440202b28 pc=0x12130bb
...additional frames elided...

Write function to customer design doc

Have you ever consider write some methods to customer design doc? For example, there is a query doc:

doc, _ := gqlparser.LoadQuery(parsedSchema, "mutation($text: String!, $userId: String!) {createTodo(input: {text: $text, userId: $userId}) {id}}")

we can customer design and change the doc ( remove or and some selection, remove or add some arguments), something like:

addArguments(doc, "key"), then the doc will be:

var buf bytes.Buffer
formatter.NewFormatter(&buf).FormatQueryDocument(doc)
fmt.Println(buf.String())

output:
mutation($text: String!, $userId: String!, $key: String!) {createTodo(input: {text: $text, userId: $userId, key: $key}) {id}}"

Schema introspection for __type should have a non-null argument

Hi,

As specified in graphql spec, introspection queries can be like:

__schema: __Schema!
__type(name: String!): __Type

i.e., argument name for __type is non-null while the field definition for __type can be null.
The same can also be verified in graphql-js implementation here.

In the current implementation of this library,

&FieldDefinition{
Name: "__type",
Type: NonNullNamedType("__Type", nil),
Arguments: ArgumentDefinitionList{
{Name: "name", Type: NamedType("String", nil)},
},
},

the name argument is defined to be nullable, while the filed definition for type is defined to be non-null.

I think this should be corrected.

reflect: call of reflect.Value.Type on zero Value

I've got this error, don't know what's going on

Using the latest gqlparser and gqlparser.

goroutine 209 [running]:
runtime/debug.Stack()
	/usr/lib/go/src/runtime/debug/stack.go:24 +0x65
runtime/debug.PrintStack()
	/usr/lib/go/src/runtime/debug/stack.go:16 +0x19
github.com/99designs/gqlgen/graphql.DefaultRecover({0xc0001226c0?, 0x0?}, {0x1052760?, 0xc00059f410?})
	/home/micro/.go/pkg/mod/github.com/99designs/[email protected]/graphql/recovery.go:17 +0x71
github.com/99designs/gqlgen/graphql/executor.(*Executor).PresentRecoveredError(0xc000119a40, {0x1359630, 0xc000542930}, {0x1052760?, 0xc00059f410?})
	/home/micro/.go/pkg/mod/github.com/99designs/[email protected]/graphql/executor/executor.go:143 +0x46
github.com/99designs/gqlgen/graphql/handler.(*Server).ServeHTTP.func1()
	/home/micro/.go/pkg/mod/github.com/99designs/[email protected]/graphql/handler/server.go:104 +0x99
panic({0x1052760, 0xc00059f410})
	/usr/lib/go/src/runtime/panic.go:838 +0x207
reflect.Value.Type({0x0?, 0x0?, 0x122a902?})
	/usr/lib/go/src/reflect/value.go:2451 +0x12e
github.com/vektah/gqlparser/v2/validator.(*varValidator).validateVarType(0xc0000ee800, 0xc00048ff50, {0x0?, 0x0?, 0x100f340?})
	/home/micro/.go/pkg/mod/github.com/vektah/gqlparser/[email protected]/validator/vars.go:105 +0xc96
github.com/vektah/gqlparser/v2/validator.(*varValidator).validateVarType(0xc0000ee800, 0xc00048ff20, {0xffd760?, 0xc00059f3e0?, 0xc00006dc50?})
	/home/micro/.go/pkg/mod/github.com/vektah/gqlparser/[email protected]/validator/vars.go:119 +0xf7c
github.com/vektah/gqlparser/v2/validator.(*varValidator).validateVarType(0xc0000ee800, 0xc000588d50, {0x1062400?, 0xc00025be90?, 0xbc373d?})
	/home/micro/.go/pkg/mod/github.com/vektah/gqlparser/[email protected]/validator/vars.go:231 +0x15c5
github.com/vektah/gqlparser/v2/validator.VariableValues(0xc0001780a0, 0xc0005298f0, 0xc0000c8090?)
	/home/micro/.go/pkg/mod/github.com/vektah/gqlparser/[email protected]/validator/vars.go:77 +0x5ce
github.com/99designs/gqlgen/graphql/executor.(*Executor).CreateOperationContext(0xc000119a40, {0x1359630, 0xc00025bdd0}, 0xc00011dc20)
	/home/micro/.go/pkg/mod/github.com/99designs/[email protected]/graphql/executor/executor.go:74 +0x48c
github.com/99designs/gqlgen/graphql/handler/transport.(*wsConnection).subscribe(0xc0002a60f0, {0xc000542930?, 0xc000171040?, 0x1a93380?}, 0xc0005435c0)
	/home/micro/.go/pkg/mod/github.com/99designs/[email protected]/graphql/handler/transport/websocket.go:307 +0x22d
github.com/99designs/gqlgen/graphql/handler/transport.(*wsConnection).run(0xc0002a60f0)
	/home/micro/.go/pkg/mod/github.com/99designs/[email protected]/graphql/handler/transport/websocket.go:237 +0x629
github.com/99designs/gqlgen/graphql/handler/transport.Websocket.Do({{0x0, 0x0, 0x0, {0x0, 0x0}, {0xc000044120, 0x2, 0x2}, 0x0, 0x0, ...}, ...}, ...)
	/home/micro/.go/pkg/mod/github.com/99designs/[email protected]/graphql/handler/transport/websocket.go:94 +0x311
github.com/99designs/gqlgen/graphql/handler.(*Server).ServeHTTP(0xc00054c480, {0x1358ef0, 0xc00021a380}, 0xc00009a600)
	/home/micro/.go/pkg/mod/github.com/99designs/[email protected]/graphql/handler/server.go:120 +0x33d

Are directive arguments checked in validation

I thought the following example would result in validation errors, but it passes without error.

Are directive arguments not checked by validation? ...or have I done something silly?

package main

import (
	"github.com/vektah/gqlparser/ast"
	"github.com/vektah/gqlparser/parser"
	"github.com/vektah/gqlparser/validator"
)

func main() {
	schema := `
scalar Int
directive @foo(bla: Int!) on FIELD_DEFINITION

type P {
	f: Int @foo(bla: "asdf")
	g: Int @foo(notblaa: "asdf")
	h: Int @foo
}
`

	doc, gqlErr := parser.ParseSchema(&ast.Source{Input: schema})
	if gqlErr != nil {
		panic(gqlErr)
	}

	_, gqlErr = validator.ValidateSchemaDocument(doc)
	if gqlErr != nil {
		panic(gqlErr)
	}
}

help: find out end position of directive

I am currently building a test tool that allows you to write queries and mutations which are run against an API endpoint. The expected result can be specified directly in the query using directives:

query QueryUserName {
  user {
     name @expect(v: "John Brown")
  }
}

My test tool then uses gqlparser to parse the directives from the query.
Before sending the query to the API endpoint I now need to cut away all @expect directives.
The query which is sent to the API should look like this:

query QueryUserName {
  user {
     name
  }
}

I originally thought that I could use the start and end of the Position struct that's attached to alt element of the directive. I later found that the Position only points to the name of the directive, not the whole thing.

Is there a way for me to find out where the directive actually ends?

validator/rules.sameArguments does not work as intended

The current implementation of sameArguments is invalid due to early exit in the loops.

https://github.com/graphql/graphql-js/blob/main/src/validation/rules/OverlappingFieldsCanBeMergedRule.ts#L626-L642

function sameArguments(
  arguments1: ReadonlyArray<ArgumentNode>,
  arguments2: ReadonlyArray<ArgumentNode>,
): boolean {
  if (arguments1.length !== arguments2.length) {
    return false;
  }
  return arguments1.every((argument1) => {
    const argument2 = arguments2.find(
      (argument) => argument.name.value === argument1.name.value,
    );
    if (!argument2) {
      return false;
    }
    return sameValue(argument1.value, argument2.value);
  });
}

As can be seen here, the first step in the loop on args1 is to discover the matching argument in args2 by name. If it can't be found, return false, otherwise true if matching or false if not โ€“ but javascript has the extra nice every option to ensure that each iteration is true.

The current golang implementation ignores the every, and as such will throw invalid if there is more than one argument in the slice.

	for _, arg1 := range args1 {
		for _, arg2 := range args2 {
			if arg1.Name != arg2.Name {
				return false
			}
			if !sameValue(arg1.Value, arg2.Value) {
				return false
			}
		}
	}
	return true

#170 also adds test cases to cover this capability.

Missing fields output shows fields that are not missing

Original Issue: 99designs/gqlgen#437

It looks like the parser is reading the schema in order and reporting on the missing field. The output shows an incorrect path to where the missing field is. It should be variables -> newTodo -> todo -> requiredTodo. I moved the fields around in the schema and verified that when I move the todo above the users in the NewTodo input it does not display the user information. After digging into the problem it looks like it is because the varValidator.path is appended to but has no concept of depth. So it does not back out twice when moving onto a new object.

POST http://localhost:8080/query
{
  "query": "mutation($newTodo: NewTodo!) { createTodo(input: $newTodo)  { id } }",
  "variables": { 
  	"newTodo": {
	  "user1": {
	  	"requiredUser": ""
	  },
	  "todo": {
	  	
	  }
	}
  }
}

Expected Behaviour

{
    "errors": [
        {
            "message": "must be defined",
            "path": [
                "variable",
                "newTodo",
                "todo",
                "requiredTodo"
            ]
        }
    ],
    "data": null
}

Actual Behavior

{
    "errors": [
        {
            "message": "must be defined",
            "path": [
                "variable",
                "newTodo",
                "user1",
                "user2",
                "todo",
                "notRequiredTodo",
                "requiredTodo"
            ]
        }
    ],
    "data": null
}

Minimal graphql.schema and models to reproduce

https://github.com/cbelsole/gql_missing_fields

Allow repeatable directives

The spec now allows the following syntax:

directive @myDirective(...) repeatable on ...

which allows you to use the same directive several times (presumably with different arguments) on the same node:

type MyType @myDirective(...) @myDirective(...) { ... }

(It's only in the working draft spec, but it's been there for several years, they just haven't released a new version; and graphql-js supports it.) This is used by Apollo's federation library (specifically their "composed SDL" uses such directives; you don't need them to use the library, but they can be useful in tooling).

But this library doesn't support it: it says Expected "on", found Name "repeatable". It would be great to add support!

formatter omits argument directives

package main

import (
	"os"

	"github.com/vektah/gqlparser/v2/ast"
	"github.com/vektah/gqlparser/v2/formatter"
	"github.com/vektah/gqlparser/v2/parser"
	"github.com/vektah/gqlparser/v2/validator"
)

func main() {
	src := ast.Source{
		Input: `
directive @dir on ARGUMENT_DEFINITION

type Query {
	get1(arg: Int = 7): Int
	get2(arg: Int): Int
	get3(arg: Int = 7 @dir): Int
	get4(arg: Int @dir): Int
}
`[1:],
	}

	doc, err := parser.ParseSchemas(validator.Prelude, &src)
	if err != nil {
		panic(err)
	}

	vdoc, err := validator.ValidateSchemaDocument(doc)
	if err != nil {
		panic(err)
	}

	formatter.NewFormatter(os.Stdout).FormatSchema(vdoc)
}

produces

type Query {
        get1(arg: Int = 7): Int
        get2(arg: Int): Int
        get3(arg: Int = 7): Int
        get4(arg: Int): Int
}

Wrong validation of non array variables

Server should coercion single value in input to list, not raise a error.

https://spec.graphql.org/June2018/#sec-Type-System.List

This causes 99designs/gqlgen#1369

t.Run("non array", func(t *testing.T) {
q := gqlparser.MustLoadQuery(schema, `query foo($var: [InputType!]) { arrayArg(i: $var) }`)
_, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{
"var": "hello",
})
require.EqualError(t, gerr, "input: variable.var must be an array")
})

similar test from graphql.js:
https://github.com/graphql/graphql-js/blob/bbd8429b85594d9ee8cc632436e2d0f900d703ef/src/execution/__tests__/variables-test.js#L341-L350

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.