Back to Skills

absinthe-resolvers

verified

Use when implementing GraphQL resolvers with Absinthe. Covers resolver patterns, dataloader integration, batching, and error handling.

View on GitHub

Marketplace

han

TheBushidoCollective/han

Plugin

jutsu-absinthe-graphql

Technique

Repository

TheBushidoCollective/han
60stars

jutsu/jutsu-absinthe-graphql/skills/absinthe-resolvers/SKILL.md

Last Verified

January 24, 2026

Install Skill

Select agents to install to:

Scope:
npx add-skill https://github.com/TheBushidoCollective/han/blob/main/jutsu/jutsu-absinthe-graphql/skills/absinthe-resolvers/SKILL.md -a claude-code --skill absinthe-resolvers

Installation paths:

Claude
.claude/skills/absinthe-resolvers/
Powered by add-skill CLI

Instructions

# Absinthe - Resolvers

Guide to implementing efficient and maintainable resolvers in Absinthe.

## Key Concepts

### Basic Resolvers

```elixir
defmodule MyApp.Resolvers.User do
  alias MyApp.Accounts

  def list_users(_parent, args, _resolution) do
    {:ok, Accounts.list_users(args)}
  end

  def get_user(_parent, %{id: id}, _resolution) do
    case Accounts.get_user(id) do
      nil -> {:error, "User not found"}
      user -> {:ok, user}
    end
  end

  def create_user(_parent, %{input: input}, _resolution) do
    case Accounts.create_user(input) do
      {:ok, user} -> {:ok, user}
      {:error, changeset} -> {:error, changeset}
    end
  end
end
```

### Resolution Context

```elixir
def current_user(_parent, _args, %{context: %{current_user: user}}) do
  {:ok, user}
end

def current_user(_parent, _args, _resolution) do
  {:error, "Not authenticated"}
end
```

### Dataloader Integration

```elixir
defmodule MyApp.Schema do
  use Absinthe.Schema

  def context(ctx) do
    loader =
      Dataloader.new()
      |> Dataloader.add_source(MyApp.Repo, Dataloader.Ecto.new(MyApp.Repo))

    Map.put(ctx, :loader, loader)
  end

  def plugins do
    [Absinthe.Middleware.Dataloader] ++ Absinthe.Plugin.defaults()
  end
end

# In type definitions
object :user do
  field :posts, list_of(:post) do
    resolve dataloader(MyApp.Repo)
  end
end
```

### Custom Dataloader Source

```elixir
defmodule MyApp.Loaders.User do
  def data() do
    Dataloader.KV.new(&fetch/2)
  end

  defp fetch(:posts_count, user_ids) do
    counts = MyApp.Posts.count_by_user_ids(user_ids)

    Map.new(user_ids, fn id ->
      {id, Map.get(counts, id, 0)}
    end)
  end
end
```

## Best Practices

1. **Use Dataloader** - Prevents N+1 queries
2. **Keep resolvers thin** - Delegate to context modules
3. **Handle errors gracefully** - Return meaningful error messages
4. **Use middleware** - For cross-cutting concerns like auth
5. **Batch related queries** - Use dataloader batching

## Middleware

```elixir

Validation Details

Front Matter
Required Fields
Valid Name Format
Valid Description
Has Sections
Allowed Tools
Instruction Length:
2719 chars