Current section

Files

Jump to
reactor lib reactor dsl argument.ex
Raw

lib/reactor/dsl/argument.ex

defmodule Reactor.Dsl.Argument do
@moduledoc """
The struct used to store `argument` DSL entities.
See `d:Reactor.step.argument`.
"""
defstruct __identifier__: nil,
name: nil,
source: nil,
transform: nil
alias Reactor.{Argument, Dsl, Template}
@type t :: %Dsl.Argument{
name: atom,
source: Template.Input.t() | Template.Result.t() | Template.Value.t(),
transform: nil | (any -> any) | {module, keyword} | mfa,
__identifier__: any
}
@doc ~S"""
The `input` template helper for the Reactor DSL.
## Example
```elixir
defmodule ExampleReactor do
use Reactor
input :name
step :greet do
# here: --------↓↓↓↓↓
argument :name, input(:name)
run fn
%{name: nil}, _, _ -> {:ok, "Hello, World!"}
%{name: name}, _, _ -> {:ok, "Hello, #{name}!"}
end
end
end
```
## Extracting nested values
You can provide a list of keys to extract from a data structure, similar to
`Kernel.get_in/2` with the condition that the input value is either a struct
or implements the `Access` protocol.
"""
@spec input(atom, [any]) :: Template.Input.t()
def input(input_name, sub_path \\ [])
def input(input_name, sub_path),
do: %Template.Input{name: input_name, sub_path: List.wrap(sub_path)}
@doc ~S"""
The `result` template helper for the Reactor DSL.
## Example
```elixir
defmodule ExampleReactor do
use Reactor
step :whom do
run fn ->
{:ok, Enum.random(["Marty", "Doc", "Jennifer", "Lorraine", "George", nil])}
end
end
step :greet do
# here: --------↓↓↓↓↓↓
argument :name, result(:whom)
run fn
%{name: nil}, _, _ -> {:ok, "Hello, World!"}
%{name: name}, _, _ -> {:ok, "Hello, #{name}!"}
end
end
end
```
## Extracting nested values
You can provide a list of keys to extract from a data structure, similar to
`Kernel.get_in/2` with the condition that the result is either a struct or
implements the `Access` protocol.
"""
@spec result(atom, [any]) :: Template.Result.t()
def result(step_name, sub_path \\ [])
def result(step_name, sub_path),
do: %Template.Result{name: step_name, sub_path: List.wrap(sub_path)}
@doc ~S"""
The `value` template helper for the Reactor DSL.
## Example
```elixir
defmodule ExampleReactor do
use Reactor
input :number
step :times_three do
argument :lhs, input(:number)
# here: -------↓↓↓↓↓
argument :rhs, value(3)
run fn args, _, _ ->
{:ok, args.lhs * args.rhs}
end
end
end
```
"""
@spec value(any) :: Template.Value.t()
def value(value), do: %Template.Value{value: value}
defimpl Argument.Build do
def build(argument) do
argument =
argument
|> Map.from_struct()
|> Map.take(~w[name source transform]a)
|> then(&struct(Argument, &1))
{:ok, [argument]}
end
end
end