# `ExRatatui.Command`
[🔗](https://github.com/mcass19/ex_ratatui/blob/v0.8.2/lib/ex_ratatui/command.ex#L1)

Commands represent one-shot side effects scheduled by an `ExRatatui.App`.

They are produced from reducer updates and executed by the ExRatatui server runtime
after the new state has been committed and rendered.

Available command constructors:

  * `message/1` — send an immediate self-message to the app process
  * `send_after/2` — schedule a delayed self-message
  * `async/2` — run a zero-arity function in the background and map the result
    back into an app message
  * `batch/1` — group multiple commands into one return value

Reducer callbacks can return commands from `init/1` or `update/2` via
`commands: [...]`.

# `async_fun`

```elixir
@type async_fun() :: (-&gt; term())
```

# `async_mapper`

```elixir
@type async_mapper() :: (term() -&gt; term())
```

# `t`

```elixir
@type t() ::
  %ExRatatui.Command{
    commands: term(),
    delay_ms: term(),
    fun: term(),
    kind: :message,
    mapper: term(),
    message: term()
  }
  | %ExRatatui.Command{
      commands: term(),
      delay_ms: non_neg_integer(),
      fun: term(),
      kind: :after,
      mapper: term(),
      message: term()
    }
  | %ExRatatui.Command{
      commands: term(),
      delay_ms: term(),
      fun: async_fun(),
      kind: :async,
      mapper: async_mapper(),
      message: term()
    }
  | %ExRatatui.Command{
      commands: [t()],
      delay_ms: term(),
      fun: term(),
      kind: :batch,
      mapper: term(),
      message: term()
    }
```

# `async`

```elixir
@spec async(async_fun(), async_mapper()) :: t()
```

Runs `fun` in the background and maps its result back into an app message.

On success, the mapper receives the function's return value directly. If the
function raises or exits, the mapper receives `{:error, reason}` where
`reason` is one of `{:exception, message}`, `{:exit, term}`, or
`{:throw | :error, term}`. Design the mapper to handle both shapes so a
failing task becomes a structured message your `update/2` (or
`handle_info/2`) can branch on.

If the mapper itself raises or exits, the app process receives
`{:error, {:mapper_exception, message}}`,
`{:error, {:mapper_exit, reason}}`, or
`{:error, {:mapper_catch, {kind, reason}}}` — distinct tags so you can
tell a task failure apart from a bug in the mapper.

## Examples

    ExRatatui.Command.async(
      fn -> MyAPI.fetch_user(id) end,
      fn
        {:ok, user} -> {:user_loaded, user}
        {:error, reason} -> {:user_load_failed, reason}
      end
    )

# `batch`

```elixir
@spec batch([t()]) :: t()
```

Groups multiple commands into a single return value.

Nested batches are flattened by the runtime before execution.

## Examples

    iex> a = ExRatatui.Command.message(:a)
    iex> b = ExRatatui.Command.send_after(10, :b)
    iex> ExRatatui.Command.batch([a, b])
    %ExRatatui.Command{
      kind: :batch,
      commands: [
        %ExRatatui.Command{kind: :message, message: :a},
        %ExRatatui.Command{kind: :after, delay_ms: 10, message: :b}
      ]
    }

# `message`

```elixir
@spec message(term()) :: t()
```

Schedules an immediate self-message for the app process.

## Examples

    iex> ExRatatui.Command.message(:tick)
    %ExRatatui.Command{kind: :message, message: :tick}

# `none`

```elixir
@spec none() :: []
```

Returns an empty command list.

Useful when reducer helpers want to return an explicit "no commands" value.

## Examples

    iex> ExRatatui.Command.none()
    []

# `send_after`

```elixir
@spec send_after(non_neg_integer(), term()) :: t()
```

Schedules a delayed self-message for the app process.

`delay_ms` may be `0` to enqueue the message on the next turn without waiting.

## Examples

    iex> ExRatatui.Command.send_after(250, :refresh)
    %ExRatatui.Command{kind: :after, delay_ms: 250, message: :refresh}

---

*Consult [api-reference.md](api-reference.md) for complete listing*
