parser provides useful errors: - name: unclosed paren input: '{' error: message: "Expected Name, found " locations: [{line: 1, column: 2}] - name: missing on in fragment input: | { ...MissingOn } fragment MissingOn Type error: message: 'Expected "on", found Name "Type"' locations: [{ line: 2, column: 20 }] - name: missing name after alias input: '{ field: {} }' error: message: "Expected Name, found {" locations: [{ line: 1, column: 10 }] - name: not an operation input: 'notanoperation Foo { field }' error: message: 'Unexpected Name "notanoperation"' locations: [{ line: 1, column: 1 }] - name: a wild splat appears input: '...' error: message: 'Unexpected ...' locations: [{ line: 1, column: 1}] variables: - name: are allowed in args input: '{ field(complex: { a: { b: [ $var ] } }) }' - name: are not allowed in default args input: 'query Foo($x: Complex = { a: { b: [ $var ] } }) { field }' error: message: 'Unexpected $' locations: [{ line: 1, column: 37 }] fragments: - name: can not be named 'on' input: 'fragment on on on { on }' error: message: 'Unexpected Name "on"' locations: [{ line: 1, column: 10 }] - name: can not spread fragments called 'on' input: '{ ...on }' error: message: 'Expected Name, found }' locations: [{ line: 1, column: 9 }] encoding: - name: multibyte characters are supported input: | # This comment has a ਊ multi-byte character. { field(arg: "Has a ਊ multi-byte character.") } ast: | Operations: [OperationDefinition] - Operation: Operation("query") SelectionSet: [Selection] - Alias: "field" Name: "field" Arguments: [Argument] - Name: "arg" Value: "Has a ਊ multi-byte character." keywords are allowed anywhere a name is: - name: on input: | query on { ... a ... on on { field } } fragment a on Type { on(on: $on) @on(on: on) } - name: subscription input: | query subscription { ... subscription ... on subscription { field } } fragment subscription on Type { subscription(subscription: $subscription) @subscription(subscription: subscription) } - name: true input: | query true { ... true ... on true { field } } fragment true on Type { true(true: $true) @true(true: true) } operations: - name: anonymous mutation input: 'mutation { mutationField }' - name: named mutation input: 'mutation Foo { mutationField }' - name: anonymous subscription input: 'subscription { subscriptionField }' - name: named subscription input: 'subscription Foo { subscriptionField }' ast: - name: simple query input: | { node(id: 4) { id, name } } ast: | Operations: [OperationDefinition] - Operation: Operation("query") SelectionSet: [Selection] - Alias: "node" Name: "node" Arguments: [Argument] - Name: "id" Value: 4 SelectionSet: [Selection] - Alias: "id" Name: "id" - Alias: "name" Name: "name" - name: nameless query with no variables input: | query { node { id } } ast: | Operations: [OperationDefinition] - Operation: Operation("query") SelectionSet: [Selection] - Alias: "node" Name: "node" SelectionSet: [Selection] - Alias: "id" Name: "id" - name: fragment defined variables input: 'fragment a($v: Boolean = false) on t { f(v: $v) }' ast: | Fragments: [FragmentDefinition] - Name: "a" VariableDefinition: [VariableDefinition] - Variable: "v" Type: Boolean DefaultValue: false TypeCondition: "t" SelectionSet: [Selection] - Alias: "f" Name: "f" Arguments: [Argument] - Name: "v" Value: $v values: - name: null input: '{ f(id: null) }' ast: | Operations: [OperationDefinition] - Operation: Operation("query") SelectionSet: [Selection] - Alias: "f" Name: "f" Arguments: [Argument] - Name: "id" Value: null - name: strings input: '{ f(long: """long""", short: "short") } ' ast: | Operations: [OperationDefinition] - Operation: Operation("query") SelectionSet: [Selection] - Alias: "f" Name: "f" Arguments: [Argument] - Name: "long" Value: "long" - Name: "short" Value: "short" - name: list input: '{ f(id: [1,2]) }' ast: | Operations: [OperationDefinition] - Operation: Operation("query") SelectionSet: [Selection] - Alias: "f" Name: "f" Arguments: [Argument] - Name: "id" Value: [1,2] types: - name: common types input: 'query ($string: String, $int: Int, $arr: [Arr], $notnull: [Arr!]!) { f }' ast: | Operations: [OperationDefinition] - Operation: Operation("query") VariableDefinitions: [VariableDefinition] - Variable: "string" Type: String - Variable: "int" Type: Int - Variable: "arr" Type: [Arr] - Variable: "notnull" Type: [Arr!]! SelectionSet: [Selection] - Alias: "f" Name: "f" large queries: - name: kitchen sink input: | # Copyright (c) 2015-present, Facebook, Inc. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. query queryName($foo: ComplexType, $site: Site = MOBILE) { whoever123is: node(id: [123, 456]) { id , ... on User @defer { field2 { id , alias: field1(first:10, after:$foo,) @include(if: $foo) { id, ...frag } } } ... @skip(unless: $foo) { id } ... { id } } } mutation likeStory { like(story: 123) @defer { story { id } } } subscription StoryLikeSubscription($input: StoryLikeSubscribeInput) { storyLikeSubscribe(input: $input) { story { likers { count } likeSentence { text } } } } fragment frag on Friend { foo(size: $size, bar: $b, obj: {key: "value", block: """ block string uses \""" """}) } { unnamed(truthy: true, falsey: false, nullish: null), query } ast: | Operations: [OperationDefinition] - Operation: Operation("query") Name: "queryName" VariableDefinitions: [VariableDefinition] - Variable: "foo" Type: ComplexType - Variable: "site" Type: Site DefaultValue: MOBILE SelectionSet: [Selection] - Alias: "whoever123is" Name: "node" Arguments: [Argument] - Name: "id" Value: [123,456] SelectionSet: [Selection] - Alias: "id" Name: "id" - TypeCondition: "User" Directives: [Directive] - Name: "defer" SelectionSet: [Selection] - Alias: "field2" Name: "field2" SelectionSet: [Selection] - Alias: "id" Name: "id" - Alias: "alias" Name: "field1" Arguments: [Argument] - Name: "first" Value: 10 - Name: "after" Value: $foo Directives: [Directive] - Name: "include" Arguments: [Argument] - Name: "if" Value: $foo SelectionSet: [Selection] - Alias: "id" Name: "id" - Name: "frag" - Directives: [Directive] - Name: "skip" Arguments: [Argument] - Name: "unless" Value: $foo SelectionSet: [Selection] - Alias: "id" Name: "id" - SelectionSet: [Selection] - Alias: "id" Name: "id" - Operation: Operation("mutation") Name: "likeStory" SelectionSet: [Selection] - Alias: "like" Name: "like" Arguments: [Argument] - Name: "story" Value: 123 Directives: [Directive] - Name: "defer" SelectionSet: [Selection] - Alias: "story" Name: "story" SelectionSet: [Selection] - Alias: "id" Name: "id" - Operation: Operation("subscription") Name: "StoryLikeSubscription" VariableDefinitions: [VariableDefinition] - Variable: "input" Type: StoryLikeSubscribeInput SelectionSet: [Selection] - Alias: "storyLikeSubscribe" Name: "storyLikeSubscribe" Arguments: [Argument] - Name: "input" Value: $input SelectionSet: [Selection] - Alias: "story" Name: "story" SelectionSet: [Selection] - Alias: "likers" Name: "likers" SelectionSet: [Selection] - Alias: "count" Name: "count" - Alias: "likeSentence" Name: "likeSentence" SelectionSet: [Selection] - Alias: "text" Name: "text" - Operation: Operation("query") SelectionSet: [Selection] - Alias: "unnamed" Name: "unnamed" Arguments: [Argument] - Name: "truthy" Value: true - Name: "falsey" Value: false - Name: "nullish" Value: null - Alias: "query" Name: "query" Fragments: [FragmentDefinition] - Name: "frag" TypeCondition: "Friend" SelectionSet: [Selection] - Alias: "foo" Name: "foo" Arguments: [Argument] - Name: "size" Value: $size - Name: "bar" Value: $b - Name: "obj" Value: {key:"value",block:"block string uses \"\"\""} fuzzer: - name: 01 input: '{__typename{...}}' error: message: 'Expected {, found }' locations: [{ line: 1, column: 16 }] - name: 02 input: '{...{__typename{...{}}}}' error: message: 'expected at least one definition, found }' locations: [{ line: 1, column: 21 }]