# `Crank.Server`
[🔗](https://github.com/code-of-kai/crank/blob/v0.2.0/lib/crank/server.ex#L1)

Runs a `Crank` callback module as a supervised `gen_statem` process.

The Server calls the same `handle/3` or `handle_event/4` functions
that `Crank.crank/2` calls. It adds what pure functions can't do:
execute timeouts, send replies, emit telemetry on every transition,
and integrate with OTP supervision.

## Two ways to use it

**Separate logic and server modules:**

    defmodule MyApp.DoorServer do
      use Crank.Server, logic: MyApp.Door
    end

    {:ok, pid} = Crank.Server.start_link(MyApp.DoorServer, [])
    Crank.Server.cast(pid, :unlock)

**Inline -- the logic module is the server module:**

    defmodule MyApp.Door do
      use Crank
      use Crank.Server

      @impl Crank
      def init(_opts), do: {:ok, :locked, %{}}

      @impl Crank
      def handle_event(_, :unlock, :locked, data), do: {:next_state, :unlocked, data}
      def handle_event(_, :lock, :unlocked, data), do: {:next_state, :locked, data}
    end

Both produce a supervised process. The callback module doesn't change.

# `on_start`

```elixir
@type on_start() :: {:ok, pid()} | :ignore | {:error, term()}
```

Return value of `start_link/3`.

# `server`

```elixir
@type server() :: GenServer.server()
```

A pid, registered name, or `{name, node}` tuple identifying a running server.

# `call`

```elixir
@spec call(server(), event :: term(), timeout()) :: term()
```

Sends a synchronous event and waits for the server to reply.

The callback module replies using `{:reply, from, response}` in its
effects list. Times out after `timeout` milliseconds (default 5000).

# `cast`

```elixir
@spec cast(server(), event :: term()) :: :ok
```

Sends an asynchronous event to the server. Returns `:ok` immediately.

# `start_link`

```elixir
@spec start_link(module(), args :: term(), keyword()) :: on_start()
```

Starts a `Crank.Server` process linked to the calling process.

Crank calls `module.init(args)` to get the starting state and data.
Pass `:name` in `opts` to register the process. All other options
are forwarded to `:gen_statem.start_link/3` (`:debug`, `:spawn_opt`, etc.).

---

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