Packages
reactor
0.7.0
1.0.2
1.0.1
1.0.0
0.17.0
0.16.0
0.15.6
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.1
0.12.0
0.11.0
0.10.3
0.10.2
0.10.1
0.10.0
0.9.1
0.9.0
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.0
0.6.0
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.0
An asynchronous, graph-based execution engine
Current section
Files
Jump to
Current section
Files
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, Step, Template}
@type t :: %Dsl.Argument{
name: atom,
source: Template.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}
@doc false
def __entity__,
do: %Spark.Dsl.Entity{
name: :argument,
describe: """
Specifies an argument to a Reactor step.
Each argument is a value which is either the result of another step, or an input value.
Individual arguments can be transformed with an arbitrary function before
being passed to any steps.
""",
examples: [
"""
argument :name, input(:name)
""",
"""
argument :year, input(:date, [:year])
""",
"""
argument :user, result(:create_user)
""",
"""
argument :user_id, result(:create_user) do
transform & &1.id
end
""",
"""
argument :user_id, result(:create_user, [:id])
""",
"""
argument :three, value(3)
"""
],
args: [:name, {:optional, :source}],
target: Dsl.Argument,
identifier: :name,
imports: [Dsl.Argument],
schema: [
name: [
type: :atom,
required: true,
doc: """
The name of the argument which will be used as the key in the `arguments` map passed to the implementation.
"""
],
source: [
type: Template.type(),
required: true,
doc: """
What to use as the source of the argument. See `Reactor.Dsl.Argument` for more information.
"""
],
transform: [
type: {:or, [{:spark_function_behaviour, Step, {Step.Transform, 1}}, nil]},
required: false,
default: nil,
doc: """
An optional transformation function which can be used to modify the argument before it is passed to the step.
"""
]
]
}
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