Current section
Files
Jump to
Current section
Files
lib/payload.ex
defmodule Freight.Payload do
use Absinthe.Schema.Notation
alias Freight.Payload.ErrorPayload
alias Freight.Payload.SuccessPayload
@doc """
Absinthe middleware function that creates a payload
## Usage
Below shows the usage in an absinthe scheme
```elixir
@desc "Delete a comment"
field :delete_comment, :comment_delete_payload do
arg(:id, non_null(:id))
resolve(&CommentsResolver.delete_comment/3)
middleware(&build_payload/2)
end
```
"""
def build_payload(%{value: value, errors: []} = resolution, _config) do
result = SuccessPayload.create_payload(value)
Absinthe.Resolution.put_result(resolution, {:ok, result})
end
def build_payload(%{errors: errors} = resolution, _config) do
result = ErrorPayload.create_payload(errors)
%{Absinthe.Resolution.put_result(resolution, {:ok, result}) | errors: []}
end
@doc """
Builds the default error object, and puts this in the config of freight.
**NOTE: calling this overwrites your config**
## Default error object
```
object :payload_error do
field(:message, type: :string)
end
```
"""
defmacro build_error_object_default() do
Application.put_env(:freight, :error_object, :payload_error)
quote do
object :payload_error do
field(:message, type: :string)
end
end
end
@doc """
Defines a payload object type with a given name and fields
## Error object
By default an error object will be generated in build_error_object_default/0.
If you'd like to use a custom error object, configure this in your config.exs:
```
config :freight,
# where :user_error is the name of the type you'd like to use as an error object
error_object: :user_error
```
Keyword list and map errors are automatically mapped to your error.
Cangeset and string errors are mapped to the `message` property.
## Usage
`define_payload(:user_payload, user: :user, comment: :comment)`
creates the equilevant of
```elixir
object :user_payload do
field(:successful,
type: non_null(:boolean),
description: "Indicates whether the mutation completed successfully or not."
)
field(:errors,
type: list_of(:payload_error),
description: "A list of errors, raised when executing this migrations."
)
field(:user, type: :user)
field(:comment, type: :comment)
end
```
"""
defmacro define_payload(name, fields \\ []) do
quote location: :keep do
# if there hasn't been a error object defined, we define the default one
unquote(
if is_nil(Freight.error_object()) do
# I tried calling build_error_object_default/0 but this broke for some reason :(
Application.put_env(:freight, :error_object, :payload_error)
quote do
object :payload_error do
field(:message, type: :string)
end
end
end
)
# define the payload
object unquote(name) do
field(:successful,
type: non_null(:boolean),
description: "Indicates whether the mutation completed successfully or not."
)
field(:errors,
type: non_null(list_of(unquote(Freight.error_object()))),
description: "A list of errors, raised when executing this migrations."
)
# loop through fields
unquote(
Enum.map(fields, fn {name, type_value} ->
quote do
field(unquote(name), type: unquote(type_value))
end
end)
)
end
end
end
end