Packages
cqrs_tools
0.5.21
0.5.28
0.5.27
0.5.26
0.5.25
0.5.24
0.5.23
0.5.22
0.5.21
0.5.20
0.5.19
0.5.18
0.5.17
0.5.16
0.5.15
0.5.14
0.5.13
0.5.12
0.5.11
0.5.10
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.19
0.4.18
0.4.17
0.4.16
0.4.15
0.4.14
0.4.13
0.4.12
0.4.11
0.4.10
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.22
0.3.21
0.3.20
0.3.19
0.3.18
0.3.17
0.3.16
0.3.15
0.3.14
0.3.13
0.3.12
0.3.11
0.3.10
0.3.9
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.30
0.2.29
0.2.28
0.2.27
0.2.26
0.2.25
0.2.24
0.2.23
0.2.22
0.2.21
0.2.20
0.2.19
0.2.18
0.2.17
0.2.16
0.2.15
0.2.14
0.2.13
0.2.12
0.2.11
0.2.10
0.2.9
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.1
0.1.0
A collection of handy Elixir macros for CQRS applications.
Current section
Files
Jump to
Current section
Files
lib/cqrs/absinthe/relay.ex
if Code.ensure_loaded?(Absinthe.Relay) do
defmodule Cqrs.Absinthe.Relay do
@moduledoc """
Macros for `Absinthe.Relay`
## Optinal Application Configuration
config :cqrs_tools, :absinthe_relay, repo: Example.Repo
"""
require Logger
alias Cqrs.Guards
alias Cqrs.Absinthe.{Relay, Query}
defmacro __using__(_) do
quote do
import Cqrs.Absinthe.Relay,
only: [
derive_connection: 3,
connection_with_total_count: 1,
connection_with_total_count: 2,
connections_with_total_count: 1
]
end
end
@doc """
Creates an `Absinthe.Relay.Connection` query from a [Command](`Cqrs.Command`).
## Options
* `:repo` - The `Ecto.Repo` to use for the connection. Defaults to the configured repo in `:cqrs_tools, :absinthe_relay`.
* `:repo_fun` - The function of the `:repo` to run. Defaults to `:all`
* `:as` - The name to use for the query. Defaults to the query_module name snake_cased.
* `:only` - Use only the filters listed
* `:except` - Create filters for all except those listed
* `:arg_types` - A list of filter names to absinthe types. See example.
* `:before_resolve` - [Absinthe Middleware](`Absinthe.Middleware`) to run before the resolver.
* `:after_resolve` - [Absinthe Middleware](`Absinthe.Middleware`) to run after the resolver.
* `:parent_mappings` - A keyword list of query filters to functions that receive the field's parent object as an argument.
* `:filter_transforms` - A keyword list of query filters to functions that receive the filter's current value as an argument.
## Example
defmodule ExampleApi.Types.UserTypes do
@moduledoc false
use Cqrs.Absinthe.Relay
use Absinthe.Schema.Notation
use Absinthe.Relay.Schema.Notation, :modern
alias Example.Queries.ListUsers
enum :user_status do
value :active
value :suspended
end
object :user do
field :id, :id
field :name, :string
field :email, :string
field :status, :user_status
derive_connection GetUserFriends, :user,
as: :friends,
repo: Example.Repo,
parent_mappings: [user_id: fn %{id: id} -> id end]
end
connection(node_type: :user)
object :user_queries do
derive_connection ListUsers, :user,
as: :users,
repo: Example.Repo,
arg_types: [status: :user_status]
end
end
"""
defmacro derive_connection(query_module, return_type, opts) do
opts =
opts
|> Keyword.merge(source: query_module, macro: :derive_connection)
|> Macro.escape()
return_type = Macro.escape(return_type)
field =
quote location: :keep do
Guards.ensure_is_query!(unquote(query_module))
Query.create_connection_query(
unquote(query_module),
unquote(return_type),
Keyword.put_new(unquote(opts), :tag?, true)
)
end
Module.eval_quoted(__CALLER__, field)
end
@doc false
def define_connection_with_total_count(node_type, opts \\ []) do
fields = Keyword.get(opts, :do)
quote do
connection node_type: unquote(node_type) do
field :total_count, :integer, resolve: &Relay.resolve_total_count/3
unquote(fields)
edge do
end
end
end
end
@doc false
def resolve_total_count(%{connection_query: query, repo: repo}, _args, _res) do
total_count = repo.aggregate(query, :count, :id)
{:ok, total_count}
end
@doc false
def resolve_total_count(_connection, _args, _res) do
Logger.warn("Requested total_count on a connection that was not created by cqrs_tools.")
{:ok, nil}
end
@doc """
Creates a connection type for each node_type. The connection will contain a `total_count` field.
"""
defmacro connection_with_total_count(node_type, opts \\ []) when is_atom(node_type) do
define_connection_with_total_count(node_type, opts)
end
@doc """
Creates a connection type for each node_type. Each connection will contain a `total_count` field.
"""
defmacro connections_with_total_count(node_types) when is_list(node_types) do
Enum.map(node_types, &define_connection_with_total_count/1)
end
end
end