defmodule SpawnSdk.Value do @moduledoc """ `Value` is a declarative DSL that provides the Domain Driven aspect of the Spawn technology. It is through a Value that the user can configure the proxy to carry out the infrastructure tasks and from which it provides all the Worflows. """ alias SpawnSdk.Flow.{Broadcast, Pipe, Forward, SideEffect} defstruct state: nil, value: nil, broadcast: nil, pipe: nil, forward: nil, effects: nil, tags: nil @type t :: %__MODULE__{ state: term(), value: term(), tags: map(), broadcast: Broadcast.t(), pipe: Pipe.t(), forward: Forward.t(), effects: list(SideEffect.t()) } @type value :: __MODULE__.t() @type broadcast :: Broadcast.t() @type effects :: list(SideEffect.t()) @type pipe :: Pipe.t() @type forward :: Forward.t() @type response :: term() @type new_state :: term() @type tags :: map() @spec of() :: value() def of(), do: %SpawnSdk.Value{} @spec of(response(), new_state()) :: value() def of(response, new_state) do struct(%SpawnSdk.Value{}, value: response, state: new_state) end @spec of(value(), response(), new_state()) :: value() def of(%SpawnSdk.Value{} = value, response, new_state) do struct(value, value: response, state: new_state) end @spec state(value(), new_state()) :: value() def state(%SpawnSdk.Value{} = value, new_state) do struct(value, state: new_state) end @spec value(value(), response()) :: value() def value(%SpawnSdk.Value{} = value, response) do struct(value, value: response) end @spec response(value(), response()) :: value() def response(%SpawnSdk.Value{} = value, response) do struct(value, value: response) end @spec broadcast(value(), broadcast()) :: value() def broadcast(%SpawnSdk.Value{} = value, broadcast) do struct(value, broadcast: broadcast) end @spec effect(value(), effects()) :: value() def effect(%SpawnSdk.Value{} = value, effect) do struct(value, effects: [effect]) end @spec effects(value(), effects()) :: value() def effects(%SpawnSdk.Value{} = value, effects) do struct(value, effects: effects) end @spec pipe(value(), pipe()) :: value() def pipe(%SpawnSdk.Value{} = value, pipe) do struct(value, pipe: pipe) end @spec forward(value(), forward()) :: value() def forward(%SpawnSdk.Value{} = value, forward) do struct(value, forward: forward) end @spec tags(value(), tags()) :: value() def tags(%SpawnSdk.Value{} = value, tags) do struct(value, tags: tags) end @spec reply!(value()) :: {:reply, value()} def reply!(%SpawnSdk.Value{state: new_state} = _value) when is_nil(new_state), do: raise("Response New State are required!") def reply!(%SpawnSdk.Value{} = value) do {:reply, value} end @spec noreply!(value()) :: {:reply, value()} def noreply!(%SpawnSdk.Value{state: new_state} = value, opts \\ []) do force = Keyword.get(opts, :force, false) if is_nil(new_state) and not force do raise("Argumenterror. Response New State are required!") end {:reply, value} end @spec noreply_state!(new_state()) :: {:reply, value()} def noreply_state!(state) do %__MODULE__{} |> state(state) |> noreply!() end @spec void() :: {:reply, value()} def void do {:reply, %SpawnSdk.Value{}} end @spec void(value()) :: {:reply, value()} def void(%SpawnSdk.Value{} = value) do {:reply, value} end end