# `Arc.Command`
[🔗](https://github.com/Cratis/Arc.Elixir/blob/main/lib/arc/command.ex#L4)

A model-bound command: a module whose struct is the request and whose `handle/2` decides.

    defmodule MyApp.Authors.Registration.RegisterAuthor do
      @moduledoc "Registers a new author."
      use Arc.Command

      schema do
        field :id, :uuid, key: true, required: true
        field :name, :string, required: true, max_length: 100
      end

      def handle(%__MODULE__{} = command, _ctx) do
        {:append, %MyApp.Authors.AuthorRegistered{name: command.name}}
      end
    end

## Callbacks

  * `provide/2` (optional) - load data after authorization and validation; return `:ok`,
    `{:ok, map}` (merged into `ctx.provided`) or `{:error, results}`.
  * `validate/2` (optional) - cross-field rules; return `:ok` or `{:error, results}`.
  * `handle/2` - decide. A command either records what happened or is rejected; it never
    succeeds as a silent no-op.

## What `handle/2` returns

  * `{:append, events}` - append one event or a list to Chronicle. The event source id is the
    command's `key: true` field; wrap an event as `{event_source_id, event}` to target another.
  * `{:append, events, response}` - append and return a value to the client.
  * `{:ok, response}` - succeed without recording an event, for example a command that only
    calls a collaborator. Prefer `{:append, ...}` for state changes.
  * `{:error, results}` - reject with a list of (or one) `Arc.ValidationResult`.

## Declarations

  * `authorize/1` and `allow_anonymous/0` - see `Arc.Authorization`
  * `response/1` - the type returned to the client, for the generated proxy

# `result`

```elixir
@type result() ::
  {:append, term()}
  | {:append, term(), term()}
  | {:ok, term()}
  | {:error, Arc.ValidationResult.t() | [Arc.ValidationResult.t()]}
```

# `handle`

```elixir
@callback handle(struct(), Arc.Context.t()) :: result()
```

# `provide`
*optional* 

```elixir
@callback provide(struct(), Arc.Context.t()) ::
  :ok
  | {:ok, map()}
  | {:error, Arc.ValidationResult.t() | [Arc.ValidationResult.t()]}
```

# `validate`
*optional* 

```elixir
@callback validate(struct(), Arc.Context.t()) ::
  :ok | {:error, Arc.ValidationResult.t() | [Arc.ValidationResult.t()]}
```

# `allow_anonymous`
*macro* 

Allows anonymous callers.

# `authorize`
*macro* 

Declares who may run the command. See `Arc.Authorization`.

# `response`
*macro* 

Declares the response type, for example `response :string` or `response MyApp.Receipt`.

---

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