Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .formatter.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ locals_without_parens = [
derive_query: 2,
derive_query: 3,
derive_mutation: 2,
derive_mutation: 3
derive_mutation: 3,
derive_input_object: 1,
derive_input_object: 2
]

[
Expand Down
9 changes: 8 additions & 1 deletion lib/cqrs/absinthe.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
defmodule Cqrs.Absinthe do
alias Cqrs.Absinthe.{Message, Mutation, Query}
alias Cqrs.Absinthe.Enum, as: AbsintheEnum
alias Cqrs.Absinthe.{Object, Message, Mutation, Query}

defmodule Error do
defexception [:message]
Expand Down Expand Up @@ -51,6 +51,13 @@ defmodule Cqrs.Absinthe do
end
end

@spec derive_input_object(atom(), keyword()) :: term()
defmacro derive_input_object(message_module, opts \\ []) do
opts = Macro.escape(opts)
object = quote do: Object.generate(:input, unquote(message_module), unquote(opts))
Module.eval_quoted(__CALLER__, object)
end

defmacro __after_compile__(_env, _bytecode) do
quote do
Enum.each(@queries, &Message.validate!(:query, &1))
Expand Down
25 changes: 20 additions & 5 deletions lib/cqrs/absinthe/args.ex → lib/cqrs/absinthe/args_and_fields.ex
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
defmodule Cqrs.Absinthe.Args do
defmodule Cqrs.Absinthe.ArgsAndFields do
@moduledoc false

# TODO: Document parent_mappings and arg_transforms

alias Cqrs.Absinthe.{Log, Type}

@spec from_message_fields(maybe_improper_list, keyword) :: list
def from_message_fields(fields, opts) when is_list(fields) do
@type arg_type :: :args | :fields
@spec from_message_fields(arg_type, list, keyword) :: list
def from_message_fields(arg_type, fields, opts) when is_list(fields) do
fields
|> filter(opts)
|> reject(:internal, opts)
|> reject(:parent_mapped_fields, opts)
|> update(:add_absinthe_types, opts)
|> update(:set_absinthe_type_opts, opts)
|> convert(:to_quoted_absinthe_args, opts)
|> convert(:to_absinthe_ast, arg_type, opts)
end

@spec resolve_message_input(map(), {atom(), map(), keyword()}) :: any
Expand All @@ -26,7 +27,7 @@ defmodule Cqrs.Absinthe.Args do
|> update(:run_arg_transforms, {message_module, arg_transforms})
end

defp convert(fields, :to_quoted_absinthe_args, opts) do
defp convert(fields, :to_absinthe_ast, :args, opts) do
declared_required_field_names = Keyword.get(opts, :required, [])

Enum.map(fields, fn {name, {_type, absinthe_type}, _field_opts} = field ->
Expand All @@ -40,6 +41,20 @@ defmodule Cqrs.Absinthe.Args do
end)
end

defp convert(fields, :to_absinthe_ast, :fields, opts) do
declared_required_field_names = Keyword.get(opts, :required, [])

Enum.map(fields, fn {name, {_type, absinthe_type}, _field_opts} = field ->
{type, opts} = absinthe_type

if required?(field, declared_required_field_names) do
quote do: field(unquote(name), non_null(unquote(type)), unquote(opts))
else
quote do: field(unquote(name), unquote(type), unquote(opts))
end
end)
end

defp required?({name, _type, field_opts}, declared_required_field_names) do
Enum.member?(declared_required_field_names, name) || Keyword.get(field_opts, :required, false)
end
Expand Down
24 changes: 6 additions & 18 deletions lib/cqrs/absinthe/field.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
defmodule Cqrs.Absinthe.Field do
alias Cqrs.DispatchContext, as: Context
alias Cqrs.Absinthe.{AbsintheErrors, Args, Field, Log, Middleware}
alias Cqrs.Absinthe.{AbsintheErrors, ArgsAndFields, Field, Log, Middleware}

@type message_module :: atom()

Expand Down Expand Up @@ -59,7 +59,7 @@ defmodule Cqrs.Absinthe.Field do
@spec args(message_module, keyword) :: list
def args(message_module, opts) do
fields = message_module.__schema_fields__()
Args.from_message_fields(fields, opts)
ArgsAndFields.from_message_fields(:args, fields, opts)
end

def description(_message_module, _opts) do
Expand All @@ -74,37 +74,25 @@ defmodule Cqrs.Absinthe.Field do

results =
args
|> Args.resolve_message_input({message_module, parent, query_opts})
|> ArgsAndFields.resolve_message_input({message_module, parent, query_opts})
|> message_module.new()
|> message_module.dispatch(opts)

:ok = Log.dump()

case results do
{:error, %Context{} = context} ->
return_value = {:error, AbsintheErrors.from_dispatch_context(context)}

context
|> Context.put_pipeline(:absinthe_resolve, return_value)
|> Context.ship()

return_value
{:error, AbsintheErrors.from_dispatch_context(context)}

{:ok, %Context{} = context} ->
return_value = {:ok, Context.get_last_pipeline(context)}

context
|> Context.put_pipeline(:absinthe_resolve, return_value)
|> Context.ship()

return_value
{:ok, Context.get_last_pipeline(context)}
end
end

def put_dispatch_opts(opts, operation, args) do
opts
|> Keyword.put(:return, :context)
|> Keyword.put(operation, true)
|> Keyword.put(:dispatched_from, operation)
|> Keyword.put(:user_supplied_fields, Map.keys(args))
end
end
27 changes: 27 additions & 0 deletions lib/cqrs/absinthe/object.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
defmodule Cqrs.Absinthe.Object do
@moduledoc false
alias Cqrs.Absinthe.{ArgsAndFields, Field}

def generate(:input, message_module, opts) do
name = :"#{Field.name(message_module, opts)}_input"

opts =
opts
|> Keyword.put(:field_name, name)
|> Keyword.put(:message_module, message_module)
|> Keyword.put(:operation, :absinthe_input_object)

fields = fields(message_module, opts)

quote do
input_object unquote(name) do
(unquote_splicing(fields))
end
end
end

defp fields(message_module, opts) do
fields = message_module.__schema_fields__()
ArgsAndFields.from_message_fields(:fields, fields, opts)
end
end
3 changes: 2 additions & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ defmodule CqrsAbsinthe.MixProject do
defp deps do
[
{:absinthe, "~> 1.7"},
{:cqrs_tools, path: "../cqrs_tools"},
# {:cqrs_tools, path: "../cqrs_tools"},
{:cqrs_tools, github: "elixir-cqrs/cqrs_tools"},
#
# test and dev deps
{:etso, "~> 0.1.6", only: [:test]},
Expand Down
1 change: 1 addition & 0 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
%{
"absinthe": {:hex, :absinthe, "1.7.0", "36819e7b1fd5046c9c734f27fe7e564aed3bda59f0354c37cd2df88fd32dd014", [:mix], [{:dataloader, "~> 1.0.0", [hex: :dataloader, repo: "hexpm", optional: true]}, {:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0 or ~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "566a5b5519afc9b29c4d367f0c6768162de3ec03e9bf9916f9dc2bcbe7c09643"},
"cqrs_tools": {:git, "https://github.com/elixir-cqrs/cqrs_tools.git", "21bc995cf87f5e1ececf1c09d36ea86fd61d7646", []},
"decimal": {:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697", [:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"},
"dialyxir": {:hex, :dialyxir, "1.1.0", "c5aab0d6e71e5522e77beff7ba9e08f8e02bad90dfbeffae60eaf0cb47e29488", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "07ea8e49c45f15264ebe6d5b93799d4dd56a44036cf42d0ad9c960bc266c0b9a"},
"ecto": {:hex, :ecto, "3.7.1", "a20598862351b29f80f285b21ec5297da1181c0442687f9b8329f0445d228892", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d36e5b39fc479e654cffd4dbe1865d9716e4a9b6311faff799b6f90ab81b8638"},
Expand Down
2 changes: 2 additions & 0 deletions test/support/schema_types.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ defmodule Cqrs.Absinthe.Test.SchemaTypes do
]
end

derive_input_object CreatePerson, arg_types: [gender: :gender]

object :person_mutations do
derive_mutation CreatePerson, :person, arg_types: [gender: :gender]
end
Expand Down