GraphQL Query Cheatsheet

View Source

This cheatsheet provides quick reference for the basic and common GraphqlQuery usage.

use GraphqlQuery

Basic Usage

defmodule MyApp.Queries do
  use GraphqlQuery
  # You have access to ~GQL sigil and other macros
end

With Options

defmodule MyApp.Queries do
  use GraphqlQuery,
    schema: MyApp.Schema,
    runtime: false,
    ignore: false,
    evaluate: false,
    fragments: [],
    format: false
end

use GraphqlQuery.Schema

Load schema from a graphql file

schema.ex

defmodule MyApp.Schema do
  use GraphqlQuery.Schema,
    schema_path: "priv/schema.graphql"
end

priv/schema.graphql

schema {
  query: RootQueryType
}

"An item"
type Item {
  id: ID
  name: String
}

type RootQueryType {
  item(id: ID!): Item
}

Manual schema module

defmodule MyApp.Schema do
  use GraphqlQuery.Schema

  @impl GraphqlQuery.Schema
  def schema do
    # Suffix "s" to parse as schema
    ~GQL""s
  end

  # Optional: By default is this module's file path
  # Can be nil, or a string. It's used for validation errors
  @impl GraphqlQuery.Schema
  def schema_path, do: nil
end

Load schema from an Absinthe schema

schema.ex

defmodule MyApp.Schema do
  use GraphqlQuery.Schema, absinthe_schema: MyAppWeb.Graphql.Schema
end

my_app_web/graphql/schema.ex

defmodule MyAppWeb.Graphql.Schema do
  use Absinthe.Schema

  @desc "An item"
  object :item do
    field(:id, :id)
    field(:name, :string)
  end

  query do
    field :item, :item do
      arg(:id, non_null(:id))

      resolve(&Resolvers.resolve_item/3)
    end
  end
end

~GQL Sigil

Queries

~GQL"""
query GetUser($id: ID!) {
  user(id: $id) {
    id
    name
    email
  }
}
"""

Fragments

~GQL"""
fragment UserFields on User {
  id
  name
  email
}
"""f # <- Important the "f" option

Mutation

~GQL"""
mutation CreateUser($input: UserInput!) {
  createUser(input: $input) {
    id
    name
  }
}
"""

Schema Definitions

~GQL"""
type User {
  id: ID!
  name: String!
  email: String!
}

type Query {
  user(id: ID!): User
}
"""s # <- Important the "s" option

Sigil Modifiers

# Ignore validation warnings
~GQL""i

# Runtime validation
~GQL""r

# Query document (default)
~GQL""q

# Fragment document
~GQL""f

# Schema document
~GQL""s

Validate with Schema

defmodule MyApp.Queries do
  use GraphqlQuery, schema: MyApp.Schema

  def get_user do
    ~GQL"""
    query GetUser($id: ID!) {
      user(id: $id) {
        id
        name
      }
    }
    """
  end
end

gql_from_file

Basic File Loading

# Load query from file
query = gql_from_file("priv/queries/get_user.graphql")

Other Options

# Load fragment from file
fragment = gql_from_file("priv/fragments/user.gql", type: :fragment)

# Load schema from file
schema = gql_from_file("priv/schema.graphql", type: :schema)

# Validate with a schema
fragment = gql_from_file("priv/fragments/user.gql", schema: MyApp.Schema)

# Add fragments
fragment = gql_from_file("priv/fragments/user.gql", fragments: [@fragments])

# Skip validation
query = gql_from_file("priv/queries/get_user.graphql", ignore: true)

# Runtime validation
query = gql_from_file("priv/queries/get_user.graphql", runtime: true)

# Apply formatting when transformed to string
query = gql_from_file("priv/queries/get_user.graphql", format: true)

document_with_options

With ~GQL sigil to validate with schema

document_with_options schema: MySchema do
  ~GQL"""
  query GetUser { user { ...UserFragment } }
  """
end

With ~GQL sigil to add fragments

@user_fragment ~GQL"""
fragment UserFields on User {
  id
  name
  email
}
"""f

document_with_options fragments: [@user_fragment] do
  ~GQL"""
  query GetUserWithFragment {
    user {
      ...UserFields
    }
  }
  """
end

gql Macro

With string interpolation

# Used only when you need to interpolate data
# But it's prefered to use variables and fragments
@fields "id name email"
query = gql "query { user { #{@fields} } }"

With Options

# With schema validation
query = gql [schema: MyApp.Schema], ""

# With fragments
query = gql [fragments: [@user_fragment]], ""

# Skip validation
query = gql [ignore: true], ""

# Runtime validation
query = gql [runtime: true], ""

# Apply automatic formatting when transforming to string
query = gql [format: true], "query{user{id name}}"

Dynamic Content

# Useful for testing if you want to build a query with dynamic fields
def build_user_query(field_list) do
  fields = Enum.join(field_list)
  gql [runtime: true], "query { user { #{fields} }"
end

With Module Schema

defmodule MyApp.Queries do
  use GraphqlQuery, schema: MyApp.Schema

  def build_query(fields) do
    gql "query { user { #{fields} } }"
  end
end

JSON encoding

With Jason

# All macros return a GraphqlDocument struct that implements Jason.Encoder
query = ~GQL"..."

Jason.encode!(query)

# {"query": "...", "variables": {}}

# You can add fragments or variables!

query
|> GraphqlQuery.Document.add_fragment(fragment)
|> GraphqlQuery.Document.add_variables(id: 123, sort: :ASC)
|> Jason.encode!()

# {"query": "... with fragment if used", "variables": {"id": 123, "sort": "ASC"}}

With JSON (Elixir >= 1.18)

# Just like Jason, it implements JSON.Encoder too and support the same features
query = ~GQL"..."

JSON.encode!(query)

# {"query": "...", "variables": {}}

to_string

Transform a document to string

# GraphqlQuery.Document and GraphqlQuery.Fragment implements `to_string`, so you can do:
# it returns the query with the needed fragments
query = ~GQL"..."

to_string(query)

"#{query}"

Format when doing to_string

# GQL sigil content is formatted automatically with mix format
# But other macros are not, if you want to format the content when
# doing to_string, you have the `format` option
# this is useful specially on testing
query = gql [format: true], ""
fragment = gql_from_document "", [format: true]


# Now it will format the content correctly!
to_string(query)
"#{fragment}"
# Even when encoding to JSON
Jason.encode!(query)

Full example!

schema.ex

defmodule Schema do
  use GraphqlQuery.Schema, schema_path: "priv/schema.graphql"
end

fragments.ex

defmodule Fragments do
  use GraphqlQuery, schema: Schema

  def user_fragment do
    ~GQL"""
    fragment UserFragment on User {
      id
      name
      email
    }
    """f
  end

  def company_fragment do
    ~GQL"""
    fragment CompanyFragment on Company {
      id
      name
    }
    """f
  end
end

priv/queries/get_user_with_company_by_id.graphql

query GetUserById($id: ID!) {
  user(id: $id) {
    ...UserFragment

    company {
      ...CompanyFragment
    }
  }
}

queries.ex

defmodule Queries do
  # The library is smart and will only add used fragments to the final query
  use GraphqlQuery, schema: Schema, fragments: [Fragments.user_fragment(), Fragments.company_fragment()]

  def user_by_id do
    ~GQL"""
    query GetUserById($id: ID!) {
      user(id: $id) {
        ...UserFragment
      }
    }
    """
  end

  def user_and_company_by_id do
    gql_from_file "priv/queries/get_user_with_company_by_id.graphql"
  end

  @post_fragment ~GQL"""
    fragment PostFragment on Post {
      id
      title
      content
    }
    """f

  def user_posts do
    # You can override the available fragments to one specific query
    document_with_options fragments: [@post_fragment] do
      ~GQL"""
      query UserPosts($id: ID!) {
        posts {
          ...PostFragment
        }
      }
      """
    end
  end
end

requests.ex

defmodule Requests do
  alias GraphqlQuery.Document

  def user_by_id(user_id) do
    query = Queries.user_by_id() |> Document.add_variables(id: user_id)
    Req.post!("/graphql", json: query)
  end

  def user_and_company_by_id(user_id) do
    query = Queries.user_and_company_by_id() |> Document.add_variables(id: user_id)
    Req.post!("/graphql", json: query)
  end

  def user_posts(user_id) do
    query = Queries.user_posts() |> Document.add_variables(id: user_id)
    Req.post!("/graphql", json: query)
  end
end