Current section
Files
Jump to
Current section
Files
lib/graphql.ex
defmodule GraphQL do
@moduledoc ~S"""
The main GraphQL module.
The `GraphQL` module provides a
[GraphQL](http://facebook.github.io/graphql/) implementation for Elixir.
## Parse a query
Parse a GraphQL query
GraphQL.parse "{ hello }"
#=> [kind: :Document, loc: [start: 0],
# definitions: [[kind: :OperationDefinition, loc: [start: 0], operation: :query,
# selectionSet: [kind: :SelectionSet, loc: [start: 0],
# selections: [[kind: :Field, loc: [start: 0], name: 'hello']]]]]]
## Execute a query
Execute a GraphQL query against a given schema / datastore.
GraphQL.execute schema, "{ hello }"
"""
defmodule Schema do
defstruct query: nil, mutation: nil
end
defmodule ObjectType do
defstruct name: "RootQueryType", description: "", fields: []
end
defmodule FieldDefinition do
defstruct name: nil, type: "String", resolve: nil
end
@doc """
Tokenize the input string into a stream of tokens.
## Examples
GraphQL.tokenize("{ hello }")
#=> [{ :"{", 1 }, { :name, 1, 'hello' }, { :"}", 1 }]
"""
def tokenize(input_string) do
{:ok, tokens, _} = :graphql_lexer.string input_string
tokens
end
@doc """
Parse the input string into a Document AST.
## Examples
GraphQL.parse("{ hello }")
#=> [kind: :Document, loc: [start: 1],
# definitions: [[kind: :OperationDefinition, loc: [start: 1], operation: :query,
# selectionSet: [kind: :SelectionSet, loc: [start: 1],
# selections: [[kind: :Field, loc: [start: 1], name: 'hello']]]]]]
"""
def parse(input_string) when is_binary(input_string) do
input_string |> to_char_list |> parse
end
def parse(input_string) do
case input_string |> tokenize |> :graphql_parser.parse do
{:ok, parse_result} ->
parse_result
{:error, {line_number, _, errors}} ->
raise GraphQL.SyntaxError, line: line_number, errors: errors
end
end
@doc """
Execute a query against a schema.
## Examples
GraphQL.execute(schema, "{ hello }")
#=> [data: [hello: world]]
"""
def execute(schema, query) do
document = parse(query)
query_fields = hd(document[:definitions])[:selectionSet][:selections]
query_field_names = for field <- query_fields, do: to_string(field[:name])
%Schema{
query: query_root = %ObjectType{
name: "RootQueryType",
fields: fields
}
} = schema
result = for fd <- fields,
qf <- query_field_names,
qf == fd.name,
do: {String.to_atom(fd.name), fd.resolve.()}
[data: result]
end
end
defmodule GraphQL.SyntaxError do
defexception line: nil, errors: "Syntax error"
def message(exception) do
"#{exception.errors} on line #{exception.line}"
end
end