Skip to content

x.graphql #

GraphQL

The x.graphql module provides parser and AST definitions for GraphQL queries, mutations, subscriptions, and Schema Definition Language (SDL) documents.

Nested nullability assertions use ListNullabilityOperatorNode.nullability_assertion, an optional pointer to NullabilityAssertionNode, to keep recursive AST nodes finite in size. ListTypeNode.node_type likewise points to its nested TypeNode.

Usage

Parsing a query

import x.graphql

doc := graphql.parse('{ hero { name } }', none)!
for def in doc.definitions {
    if def is graphql.OperationDefinitionNode {
        for sel in def.selection_set.selections {
            if sel is graphql.FieldNode {
                println('Field: ${sel.name.value}')
            }
        }
    }
}

Parsing schema definition (SDL)

import x.graphql

sdl := '
type User {
    id: ID!
    name: String!
}
'

doc := graphql.parse(sdl, none)!
for def in doc.definitions {
    if def is graphql.ObjectTypeDefinitionNode {
        println('Type: ${def.name.value}')
    }
}

Parser options

You can control token limits and source location tracking via ParserOptions:

import x.graphql

options := graphql.ParserOptions{
    no_location: true
    max_tokens:  10_000
}
doc := graphql.parse('{ ping }', options)!

fn get_location #

fn get_location(source Source, position int) !SourceLocation

getLocation takes a Source and a UTF-8 character offset, and returns the corresponding line and column as a SourceLocation.

fn is_printable_as_block_string #

fn is_printable_as_block_string(value string) bool

Check if a string is printable as a block string.

fn parse #

fn parse(source SourceOrString, options ?ParserOptions) !DocumentNode

fn DirectiveLocation.from #

fn DirectiveLocation.from[W](input W) !DirectiveLocation

from returns the DirectiveLocation value of an integer or of a field name, or an error if there is none.

fn Kind.from #

fn Kind.from[W](input W) !Kind

from returns the Kind value of an integer or of a field name, or an error if there is none.

fn OperationTypeNode.from #

fn OperationTypeNode.from[W](input W) !OperationTypeNode

from returns the OperationTypeNode value of an integer or of a field name, or an error if there is none.

fn TokenKind.from #

fn TokenKind.from[W](input W) !TokenKind

from returns the TokenKind value of an integer or of a field name, or an error if there is none.

interface ASTNodeInterface #

interface ASTNodeInterface {
mut:
	loc ?Location
}

All AST Nodes should implement a MUTable common loc property

interface IDirectiveNode #

interface IDirectiveNode {
	kind      Kind
	name      NameNode
	arguments ?[]ArgumentNode
mut:
	loc ?Location
}

type ASTNode #

type ASTNode = ArgumentNode
	| BooleanValueNode
	| DirectiveDefinitionNode
	| DirectiveNode
	| DocumentNode
	| EnumTypeDefinitionNode
	| EnumTypeExtensionNode
	| EnumValueDefinitionNode
	| EnumValueNode
	| ErrorBoundaryNode
	| FieldDefinitionNode
	| FieldNode
	| FloatValueNode
	| FragmentDefinitionNode
	| FragmentSpreadNode
	| InlineFragmentNode
	| InputObjectTypeDefinitionNode
	| InputObjectTypeExtensionNode
	| InputValueDefinitionNode
	| IntValueNode
	| InterfaceTypeDefinitionNode
	| InterfaceTypeExtensionNode
	| ListNullabilityOperatorNode
	| ListTypeNode
	| ListValueNode
	| NameNode
	| NamedTypeNode
	| NonNullAssertionNode
	| NonNullTypeNode
	| NullValueNode
	| ObjectFieldNode
	| ObjectTypeDefinitionNode
	| ObjectTypeExtensionNode
	| ObjectValueNode
	| OperationDefinitionNode
	| OperationTypeDefinitionNode
	| ScalarTypeDefinitionNode
	| ScalarTypeExtensionNode
	| SchemaDefinitionNode
	| SchemaExtensionNode
	| SelectionSetNode
	| StringValueNode
	| UnionTypeDefinitionNode
	| UnionTypeExtensionNode
	| VariableDefinitionNode
	| VariableNode

The list of all possible AST node types.

type DefinitionNode #

type DefinitionNode = DirectiveDefinitionNode
	| EnumTypeDefinitionNode
	| FragmentDefinitionNode
	| InputObjectTypeDefinitionNode
	| InterfaceTypeDefinitionNode
	| ObjectTypeDefinitionNode
	| OperationDefinitionNode
	| ScalarTypeDefinitionNode
	| SchemaDefinitionNode
	| SchemaExtensionNode
	| TypeExtensionNode
	| UnionTypeDefinitionNode

type ExecutableDefinitionNode #

type ExecutableDefinitionNode = FragmentDefinitionNode | OperationDefinitionNode

type NonNullType #

type NonNullType = ListTypeNode | NamedTypeNode

type NullabilityAssertionNode #

type NullabilityAssertionNode = ErrorBoundaryNode
	| ListNullabilityOperatorNode
	| NonNullAssertionNode

type SelectionNode #

type SelectionNode = FieldNode | FragmentSpreadNode | InlineFragmentNode

type TypeDefinitionNode #

type TypeDefinitionNode = EnumTypeDefinitionNode
	| InputObjectTypeDefinitionNode
	| InterfaceTypeDefinitionNode
	| ObjectTypeDefinitionNode
	| ScalarTypeDefinitionNode
	| UnionTypeDefinitionNode

type TypeDirectives #

type TypeDirectives = DirectiveNode

type TypeExtensionNode #

type TypeExtensionNode = EnumTypeExtensionNode
	| InputObjectTypeExtensionNode
	| InterfaceTypeExtensionNode
	| ObjectTypeExtensionNode
	| ScalarTypeExtensionNode
	| UnionTypeExtensionNode

type TypeNode #

type TypeNode = ListTypeNode | NamedTypeNode | NonNullTypeNode

type TypeSystemDefinitionNode #

type TypeSystemDefinitionNode = DirectiveDefinitionNode
	| SchemaDefinitionNode
	| TypeDefinitionNode

type TypeSystemExtensionNode #

type TypeSystemExtensionNode = SchemaExtensionNode | TypeExtensionNode

type ValueNode #

type ValueNode = BooleanValueNode
	| ConstObjectValueNode
	| EnumValueNode
	| FloatValueNode
	| IntValueNode
	| ListValueNode
	| NullValueNode
	| ObjectValueNode
	| StringValueNode
	| VariableNode

--

enum DirectiveLocation #

enum DirectiveLocation {
	// Request Definitions
	query
	mutation
	subscription
	field
	fragment_definition
	fragment_spread
	inline_fragment
	variable_definition
	// Type System Definitions
	schema
	scalar
	object
	field_definition
	argument_definition
	@interface
	@union
	@enum
	enum_value
	input_object
	input_field_definition
}

enum Kind #

enum Kind {
	name
	document
	// Documen
	operation_definition
	variable_definition
	selection_set
	field
	argument
	// Nullability Modifier
	list_nullability_operator
	non_null_assertion
	error_boundary
	// Fragments *
	fragment_spread
	inline_fragment
	fragment_definition
	// Value
	variable
	int_value
	float_value
	string_value
	boolean
	null
	enum_value
	list
	object
	object_field
	// Directive
	directive
	// Type
	named_type
	list_type
	non_null_type
	// Type System Definition
	schema_definition
	operation_type_definition
	// Type Definition
	scalar_type_definition
	object_type_definition
	field_definition
	input_value_definition
	interface_type_definition
	union_type_definition
	enum_type_definition
	enum_value_definition
	input_object_type_definition
	// Directive Definition
	directive_definition
	// Type System Extension
	schema_extension
	// Type Extension
	scalar_type_extension
	object_type_extension
	interface_type_extension
	union_type_extension
	enum_type_extension
	input_object_type_extension
}

fn (Kind) gql_str #

fn (k Kind) gql_str() string

Returns the string value of the Kind enum

enum OperationTypeNode #

enum OperationTypeNode {
	query
	mutation
	subscription
}

fn (OperationTypeNode) gql_str #

fn (o OperationTypeNode) gql_str() string

enum TokenKind #

enum TokenKind {
	sof
	eof
	bang
	question_mark
	dollar
	amp
	paren_l
	paren_r
	spread
	colon
	equals
	at
	bracket_l
	bracket_r
	brace_l
	pipe
	brace_r
	name
	integer
	float
	string_value
	block_string
	comment
}

An exported enum describing the different kinds of tokens that the lexer emits.

fn (TokenKind) gql_str #

fn (t TokenKind) gql_str() string

Returns the character value of the TokenKind enum

struct BlockStringOptions #

struct BlockStringOptions {
pub:
	minimize bool
}

struct BooleanValueNode #

struct BooleanValueNode {
pub:
	kind     Kind = Kind.boolean
	value    bool
	is_const bool
pub mut:
	loc ?Location
}

struct ConstArgumentNode #

struct ConstArgumentNode {
pub:
	kind  Kind = Kind.argument
	name  NameNode
	value ValueNode
pub mut:
	loc ?Location
}

struct ConstObjectFieldNode #

struct ConstObjectFieldNode {
pub:
	kind     Kind = Kind.object_field
	name     NameNode
	value    ValueNode
	is_const bool = true
pub mut:
	loc ?Location
}

struct ConstObjectValueNode #

struct ConstObjectValueNode {
pub:
	kind     Kind = Kind.object
	fields   []ValueNode
	is_const bool = true
pub mut:
	loc ?Location
}

struct DirectiveDefinitionNode #

struct DirectiveDefinitionNode {
pub:
	kind        Kind = Kind.directive_definition
	description ?StringValueNode
	name        NameNode
	arguments   ?[]InputValueDefinitionNode
	repeatable  bool
	locations   []NameNode
pub mut:
	loc ?Location
}

struct DirectiveNode #

struct DirectiveNode {
pub:
	kind      Kind = Kind.directive
	name      NameNode
	arguments ?[]ArgumentNode
pub mut:
	loc      ?Location
	is_const bool
}

struct DocumentNode #

struct DocumentNode {
pub:
	kind        Kind = Kind.document
	definitions []DefinitionNode
	token_count int
pub mut:
	loc ?Location
}

struct EnumTypeDefinitionNode #

struct EnumTypeDefinitionNode {
pub:
	kind        Kind = Kind.enum_type_definition
	description ?StringValueNode
	name        NameNode
	directives  ?[]DirectiveNode
	values      ?[]EnumValueDefinitionNode
pub mut:
	loc ?Location
}

struct EnumTypeExtensionNode #

struct EnumTypeExtensionNode {
pub:
	kind       Kind = Kind.enum_type_extension
	name       NameNode
	directives ?[]DirectiveNode
	values     ?[]EnumValueDefinitionNode
pub mut:
	loc ?Location
}

struct EnumValueDefinitionNode #

struct EnumValueDefinitionNode {
pub:
	kind        Kind = Kind.enum_value_definition
	description ?StringValueNode
	name        NameNode
	directives  ?[]DirectiveNode
pub mut:
	loc ?Location
}

struct EnumValueNode #

struct EnumValueNode {
pub:
	kind     Kind = Kind.enum_value
	value    string
	is_const bool
pub mut:
	loc ?Location
}

struct ErrorBoundaryNode #

struct ErrorBoundaryNode {
pub:
	kind                  Kind = Kind.error_boundary
	nullability_assertion ?ListNullabilityOperatorNode
pub mut:
	loc ?Location
}

struct FieldDefinitionNode #

struct FieldDefinitionNode {
pub:
	kind        Kind = Kind.field_definition
	description ?StringValueNode
	name        NameNode
	arguments   ?[]InputValueDefinitionNode
	@type       TypeNode
	directives  ?[]DirectiveNode
pub mut:
	loc ?Location
}

struct FieldNode #

struct FieldNode {
pub:
	kind                  Kind = Kind.field
	alias                 ?NameNode
	name                  NameNode
	arguments             ?[]ArgumentNode
	nullability_assertion ?NullabilityAssertionNode
	directives            []DirectiveNode
	selection_set         ?SelectionSetNode
pub mut:
	loc ?Location
}

struct FloatValueNode #

struct FloatValueNode {
pub:
	kind     Kind = Kind.float_value
	value    ?string
	is_const bool
pub mut:
	loc ?Location
}

struct FragmentDefinitionNode #

struct FragmentDefinitionNode {
pub:
	kind           Kind = Kind.fragment_definition
	name           NameNode
	type_condition NamedTypeNode
	directives     []DirectiveNode
	selection_set  SelectionSetNode
pub mut:
	loc ?Location
}

struct FragmentSpreadNode #

struct FragmentSpreadNode {
pub:
	kind       Kind = Kind.fragment_spread
	name       NameNode
	directives ?[]DirectiveNode
pub mut:
	loc ?Location
}

Fragments

struct InlineFragmentNode #

struct InlineFragmentNode {
pub:
	kind           Kind = Kind.inline_fragment
	type_condition ?NamedTypeNode
	directives     ?[]DirectiveNode
	selection_set  SelectionSetNode
pub mut:
	loc ?Location
}

struct InputObjectTypeDefinitionNode #

struct InputObjectTypeDefinitionNode {
pub:
	kind        Kind = Kind.input_object_type_definition
	description ?StringValueNode
	name        NameNode
	directives  ?[]DirectiveNode
	fields      ?[]InputValueDefinitionNode
pub mut:
	loc ?Location
}

struct InputObjectTypeExtensionNode #

struct InputObjectTypeExtensionNode {
pub:
	kind       Kind = Kind.object_type_extension
	name       NameNode
	directives ?[]DirectiveNode
	fields     ?[]InputValueDefinitionNode
pub mut:
	loc ?Location
}

struct InputValueDefinitionNode #

struct InputValueDefinitionNode {
pub:
	kind          Kind
	description   ?StringValueNode
	name          NameNode
	@type         TypeNode
	default_value ?ValueNode
	directives    ?[]DirectiveNode
pub mut:
	loc ?Location
}

struct IntValueNode #

struct IntValueNode {
pub:
	kind     Kind = Kind.int_value
	value    ?string
	is_const bool
pub mut:
	loc ?Location
}

struct InterfaceTypeDefinitionNode #

struct InterfaceTypeDefinitionNode {
pub:
	kind        Kind = Kind.interface_type_definition
	description ?StringValueNode
	name        NameNode
	interfaces  ?[]NamedTypeNode
	directives  ?[]DirectiveNode
	fields      ?[]FieldDefinitionNode
pub mut:
	loc ?Location
}

struct InterfaceTypeExtensionNode #

struct InterfaceTypeExtensionNode {
pub:
	kind       Kind = Kind.interface_type_extension
	name       NameNode
	interfaces ?[]NamedTypeNode
	directives ?[]DirectiveNode
	fields     ?[]FieldDefinitionNode
pub mut:
	loc ?Location
}

struct Lexer #

struct Lexer {
pub:
	source Source
mut:
	line_start int
	line       int
	last_token &Token
	token      &Token
}

struct ListNullabilityOperatorNode #

struct ListNullabilityOperatorNode {
pub:
	kind                  Kind = Kind.list_nullability_operator
	nullability_assertion ?&NullabilityAssertionNode
pub mut:
	loc ?Location
}

struct ListTypeNode #

struct ListTypeNode {
pub:
	kind      Kind = Kind.list_type
	node_type &TypeNode
pub mut:
	loc ?Location
}

struct ListValueNode #

struct ListValueNode {
pub:
	kind     Kind = Kind.list
	values   []ValueNode
	is_const bool
pub mut:
	loc ?Location
}

struct Location #

struct Location {
pub:
	// The character offset at which this Node begins.
	start int
	// The character offset at which this Node ends.
	end int
	// The Token at which this Node begins.
	start_token ?&Token
	// The Token at which this Node ends.
	end_token ?&Token
	// The Source document the AST represents.
	source Source
}

struct NameNode #

struct NameNode {
pub:
	kind  Kind = Kind.name
	value string
pub mut:
	loc ?Location
}

struct NamedTypeNode #

struct NamedTypeNode {
pub:
	kind      Kind = Kind.named_type
	node_type NameNode
pub mut:
	loc ?Location
}

struct NonNullAssertionNode #

struct NonNullAssertionNode {
pub:
	kind                  Kind = Kind.non_null_assertion
	nullability_assertion ?ListNullabilityOperatorNode
pub mut:
	loc ?Location
}

struct NonNullTypeNode #

struct NonNullTypeNode {
pub:
	kind      Kind = Kind.non_null_type
	node_type NonNullType
pub mut:
	loc ?Location
}

struct NullValueNode #

struct NullValueNode {
pub:
	kind     Kind = Kind.null
	is_const bool
pub mut:
	loc ?Location
}

struct ObjectFieldNode #

struct ObjectFieldNode {
pub:
	kind     Kind = Kind.object_field
	name     NameNode
	value    ValueNode
	is_const bool
pub mut:
	loc ?Location
}

struct ObjectTypeDefinitionNode #

struct ObjectTypeDefinitionNode {
pub:
	kind        Kind
	description ?StringValueNode
	name        NameNode
	interfaces  ?[]NamedTypeNode
	directives  ?[]DirectiveNode
	fields      ?[]FieldDefinitionNode
pub mut:
	loc ?Location
}

struct ObjectTypeExtensionNode #

struct ObjectTypeExtensionNode {
pub:
	kind       Kind = Kind.object_type_extension
	name       NameNode
	interfaces ?[]NamedTypeNode
	directives ?[]DirectiveNode
	fields     ?[]FieldDefinitionNode
pub mut:
	loc ?Location
}

struct ObjectValueNode #

struct ObjectValueNode {
pub:
	kind     Kind = Kind.object
	fields   []ObjectFieldNode
	is_const bool
pub mut:
	loc ?Location
}

struct OperationDefinitionNode #

struct OperationDefinitionNode {
pub:
	kind                 Kind = Kind.operation_definition
	operation            OperationTypeNode
	name                 ?NameNode
	variable_definitions ?[]VariableDefinitionNode
	directives           ?[]DirectiveNode
	selection_set        SelectionSetNode
pub mut:
	loc ?Location
}

struct OperationTypeDefinitionNode #

struct OperationTypeDefinitionNode {
pub:
	kind      Kind = Kind.operation_type_definition
	operation OperationTypeNode
	@type     NamedTypeNode
pub mut:
	loc ?Location
}

struct Parser #

struct Parser {
	options ParserOptions
mut:
	lexer         Lexer
	token_counter int
}

struct ParserOptions #

struct ParserOptions {
pub:
	// By default, the parser creates AST nodes that know the location
	// in the source that they correspond to. This configuration flag
	// disables that behavior for performance or testing.
	no_location bool
	// Parser CPU and memory usage is linear to the number of tokens in a document
	// however in extreme cases it becomes quadratic due to memory exhaustion.
	// Parsing happens before validation so even invalid queries can burn lots of
	// CPU time and memory.
	// To prevent this you can set a maximum number of tokens allowed within a document.
	// @default 50K tokens
	max_tokens int = 50_000
	// @deprecated
	allow_legacy_fragment_variables            ?bool
	experimental_client_controlled_nullability ?bool
}

struct ScalarTypeDefinitionNode #

struct ScalarTypeDefinitionNode {
pub:
	kind        Kind
	description ?StringValueNode
	name        NameNode
	directives  ?[]DirectiveNode
pub mut:
	loc ?Location
}

struct ScalarTypeExtensionNode #

struct ScalarTypeExtensionNode {
pub:
	kind       Kind = Kind.scalar_type_extension
	name       NameNode
	directives ?[]DirectiveNode
pub mut:
	loc ?Location
}

struct SchemaDefinitionNode #

struct SchemaDefinitionNode {
pub:
	kind            Kind = Kind.schema_definition
	description     ?StringValueNode
	directives      ?[]DirectiveNode
	operation_types []OperationTypeDefinitionNode
pub mut:
	loc ?Location
}

struct SchemaExtensionNode #

struct SchemaExtensionNode {
pub:
	kind            Kind = Kind.schema_extension
	directives      ?[]DirectiveNode
	operation_types ?[]OperationTypeDefinitionNode
pub mut:
	loc ?Location
}

struct SelectionSetNode #

struct SelectionSetNode {
pub:
	kind       Kind = Kind.selection_set
	selections []SelectionNode
pub mut:
	loc ?Location
}

struct Source #

struct Source {
pub:
	body            string
	name            string
	location_offset LocationOffset
}

A representation of source input to GraphQL. The name and locationOffset parameters are optional, but they are useful for clients who store GraphQL documents in source files. For example, if the GraphQL input starts at line 40 in a file named Foo.graphql, it might be useful for name to be "Foo.graphql" and location to be { line: 40, column: 1 }. The line and column properties in locationOffset are 1-indexed.

struct StringValueNode #

struct StringValueNode {
pub:
	kind     Kind = Kind.string_value
	value    ?string
	block    ?bool
	is_const bool
pub mut:
	loc ?Location
}

struct Token #

@[heap]
struct Token {
pub:
	kind TokenKind
	// The character offset at which this Node begins.
	start int
	// The character offset at which this Node ends.
	end int
	// The 1-indexed line number on which this Token appears.
	line int
	// The 1-indexed column number at which this Token begins.
	column int
	// For non-punctuation tokens, represents the interpreted value of the token.
	// <br>
	// **Note**: is `none` for punctuation tokens, but typed as string for
	// convenience in the parser.
	value ?string
mut:
	// Tokens exist as nodes in a double-linked-list amongst all tokens
	// including ignored tokens. <SOF> is always the first node and <EOF>
	// the last.
	prev ?&Token
	next ?&Token
}

struct UnionTypeDefinitionNode #

struct UnionTypeDefinitionNode {
pub:
	kind        Kind = Kind.union_type_definition
	description ?StringValueNode
	name        NameNode
	directives  ?[]DirectiveNode
	types       ?[]NamedTypeNode
pub mut:
	loc ?Location
}

struct UnionTypeExtensionNode #

struct UnionTypeExtensionNode {
pub:
	kind       Kind = Kind.union_type_extension
	name       NameNode
	directives ?[]DirectiveNode
	types      ?[]NamedTypeNode
pub mut:
	loc ?Location
}

struct VariableDefinitionNode #

struct VariableDefinitionNode {
pub:
	kind          Kind = Kind.variable_definition
	variable      VariableNode
	@type         TypeNode
	default_value ?ValueNode
	directives    ?[]DirectiveNode
pub mut:
	loc ?Location
}

struct VariableNode #

struct VariableNode {
pub:
	kind Kind = Kind.variable
	name NameNode
pub mut:
	loc ?Location
}