absinthe v0.2.2 Absinthe

Documentation for the Absinthe package, a toolkit for building GraphQL APIs with Elixir.

Absinthe aims to handle authoring GraphQL API schemas — then supporting their introspection, validation, and execution according to the GraphQL specification.

Building HTTP APIs

IMPORTANT: For HTTP, you’ll probably want to use AbsinthePlug instead of executing GraphQL query documents yourself. Absinthe doesn’t know or care about HTTP, so keep that in mind while reading through the documentation. While you’ll be building schemas just as in the examples here, the actual calls to Absinthe.run/3 and its friends are best left to AbsinthePlug if you’re providing an HTTP API.

Ecosystem

Here are some additional projects you’re likely to use in conjunction with Absinthe to launch an API:

  • Ecto - a language integrated query and database wrapper.
  • Phoenix - the Phoenix web framework.
  • Plug - a specification and conveniences for composable modules in between web applications.
  • Poison - JSON serialization.

GraphQL Basics

For a grounding in GraphQL, I recommend you read through the following articles:

You may also be interested in how GraphQL is used by Relay, a “JavaScript frameword for building data-driven React applications.”

GraphQL using Absinthe

The first thing you need to do is define a schema, we do this by using Absinthe.Schema.

Here we’ll build a basic schema that defines one query field; a way to retrieve the data for an item, given an id. Users of the API can then decide what fields of the item they’d like returned.

defmodule App.Schema do

  use Absinthe.Schema

  @fake_db %{
    "foo" => %{id: "foo", name: "Foo", value: 4},
    "bar" => %{id: "bar", name: "Bar", value: 5}
  }

  def query do
    %Absinthe.Type.Object{
      fields: fields(
        item: [
          type: :item,
          description: "Get an item by ID",
          args: args(
            id: [type: :id, description: "The ID of the item"]
          ),
          resolve: fn %{id: id}, _ ->
            {:ok, Map.get(@fake_db, id)}
          end
        ]
      )
    }
  end

  @absinthe :type
  def item do
    %Absinthe.Type.Object{
      description: "A valuable item",
      fields: fields(
        id: [type: :id],
        name: [type: :string, description: "The item's name"],
        value: [type: :integer, description: "Recently appraised value"]
      )
    }
  end

end

Now we’ll execute a query document against it with run/2 or run/3 (which return tuples), or their exception-raising equivalents, run!/2 and `run!/3.

Let’s get the name of an item with id "foo":

"""
{
  item(id: "foo") {
    name
  }
}
"""
|> Absinthe.run(App.Schema)

Results are returned in a tuple, and are maps with :data and/or :errors keys, suitable for serialization back to the client.

{:ok, %{data: %{"name" => "Foo"}}}

You can also provide values for variables defined in the query document (supporting, eg, values passed as query string parameters):

"""
query GetItemById($id: ID) {
  item(id: $id) {
    name
  }
}
"""
|> Absinthe.run(App.Schema, variables: %{id: params[:item_id]})

The result, if params[:item_id] was "foo", would be the same:

{:ok, %{data: %{"name" => "Foo"}}}

run!/2 and run!/3 operate similarly, except they will raise Absinthe.SytaxError and Absinthe.ExecutionError if they cannot parse/execute the document.

Summary

Functions

Evaluates a query document against a schema, without options

Evaluates a query document against a schema, with options

Evaluates a query document against a schema, with options, raising an Absinthe.SyntaxErorr or Absinthe.ExecutionError if a problem occurs

Evaluates a query document against a schema, without options

Validate a document

Functions

run(input, schema)

Specs

run(binary | Absinthe.Language.Source.t | Absinthe.Language.Document.t, atom | Absinthe.Schema.t) ::
  {:ok, Absinthe.Execution.result_t} |
  {:error, any}

Evaluates a query document against a schema, without options.

Examples

"""
{
  item(id: "foo") {
    name
  }
}
"""
|> Absinthe.run(App.Schema)

Also see Absinthe.run/3

run(document, schema, options)

Specs

run(binary | Absinthe.Language.Source.t | Absinthe.Language.Document.t, atom | Absinthe.Schema.t, Keyword.t) ::
  {:ok, Absinthe.Execution.result_t} |
  {:error, any}

Evaluates a query document against a schema, with options.

Options

Examples

"""
query GetItemById($id: ID) {
  item(id: $id) {
    name
  }
}
"""
|> Absinthe.run(App.Schema, variables: %{id: params[:item_id]})

See the Absinthe module documentation for more examples.

run!(input, schema)

Specs

run!(binary | Absinthe.Language.Source.t | Absinthe.Language.Document.t, atom | Absinthe.Schema.t) :: Absinthe.Execution.result_t

Evaluates a query document against a schema, with options, raising an Absinthe.SyntaxErorr or Absinthe.ExecutionError if a problem occurs.

run!(input, schema, options)

Specs

run!(binary | Absinthe.Language.Source.t | Absinthe.Language.Document.t, atom | Absinthe.Schema.t, Keyword.t) :: Absinthe.Execution.result_t

Evaluates a query document against a schema, without options.

Options

See run/3 for the available options.

validate(doc, schema)

Specs

validate(Language.Document.t, atom | Schema.t) :: :ok

Validate a document.

Note this is currently a stub that merely returns :ok, as validation and execution are currently conflated.

Track https://github.com/CargoSense/absinthe/issues/17 for progress.