# `LiveStash`
[🔗](https://github.com/software-mansion-labs/live-stash/blob/v0.1.2/lib/live_stash.ex#L1)

Main public API for stashing and recovering `Phoenix.LiveView` assigns.

`LiveStash` helps preserve selected server-side assigns across reconnects.
You explicitly choose which assigns to persist and when to persist them.

This module:

- integrates with `on_mount` via `use LiveStash`
- initializes the selected adapter
- delegates persistence and recovery operations to that adapter

## Quick start

Add `use LiveStash` to your LiveView:

    defmodule MyAppWeb.CounterLive do
      use MyAppWeb, :live_view
      use LiveStash
    end

Stash assigns after state-changing events:

    def handle_event("increment", _, socket) do
      socket
      |> assign(:count, socket.assigns.count + 1)
      |> LiveStash.stash_assigns([:count])
      |> then(&{:noreply, &1})
    end

Recover stashed state in `mount/3`:

    def mount(_params, _session, socket) do
      socket
      |> LiveStash.recover_state()
      |> case do
        {:recovered, recovered_socket} ->
          # socket with previously stashed assigns is recovered
          recovered_socket

        {_, socket} ->
          # could not recover assigns, proceed with standard setup using returned socket
          # ...
      end
      |> then(&{:ok, &1})
    end

## Recovery statuses

`recover_state/1` returns `{status, socket}` where `status` is one of:

- `:new` - fresh LiveView process, with no previously stashed state
- `:recovered` - state was found and applied
- `:not_found` - state was not found for this LiveView
- `:error` - adapter failed to recover state

## Adapter selection

The default adapter is `LiveStash.Adapters.BrowserMemory`.
You can override it per LiveView:

    use LiveStash, adapter: LiveStash.Adapters.ETS

Adapters used by your app must also be enabled in config:

    config :live_stash,
      adapters: [LiveStash.Adapters.BrowserMemory, LiveStash.Adapters.ETS]

# `recovery_status`

```elixir
@type recovery_status() :: :recovered | :not_found | :new | :error
```

# `__using__`
*macro* 

Injects LiveStash support into a `Phoenix.LiveView`. This macro expands to:

    on_mount({LiveStash, opts})

so that LiveStash can initialize stash handling during the LiveView `mount/3`
lifecycle.

## Options

The `opts` are forwarded to `LiveStash.on_mount/4` and ultimately to the
configured adapter. Most adapters use `:adapter` to select the persistence
backend:

    use LiveStash, adapter: LiveStash.Adapters.ETS

Note: adapters must also be enabled in `config :live_stash, :adapters`.

## Example

    defmodule MyAppWeb.CounterLive do
      use MyAppWeb, :live_view
      use LiveStash, adapter: LiveStash.Adapters.BrowserMemory
    end

# `init_stash`

```elixir
@spec init_stash(
  socket :: Phoenix.LiveView.Socket.t(),
  session :: Keyword.t(),
  opts :: Keyword.t()
) ::
  Phoenix.LiveView.Socket.t()
```

Initializes stash support for a socket using the configured adapter.

This function is called from `on_mount/4`. In normal usage, prefer
`use LiveStash` and do not call this function directly.

It validates that the selected adapter is active in
`config :live_stash, :adapters`.

# `on_mount`

LiveView `on_mount` callback used by `use LiveStash`.

It initializes stash handling for the current socket and continues the mount
lifecycle.

# `recover_state`

```elixir
@spec recover_state(socket :: Phoenix.LiveView.Socket.t()) ::
  {recovery_status(), Phoenix.LiveView.Socket.t()}
```

Recovers previously stashed state and returns `{status, socket}`.

This function is typically called in `mount/3`. Recovery does not clear the
stored state; use `reset_stash/1` when you want to remove it explicitly.

## Examples
    def mount(_params, _session, socket) do
      socket
      |> LiveStash.recover_state()
      |> case do
        {:recovered, recovered_socket} ->
          recovered_socket

        {_, socket} ->
          start_new_game(socket)
      end
      |> then(&{:ok, &1})
    end

# `reset_stash`

```elixir
@spec reset_stash(socket :: Phoenix.LiveView.Socket.t()) ::
  Phoenix.LiveView.Socket.t()
```

Clears stashed state for the current LiveView socket.

## Examples
    def handle_event("restart_game", _params, socket) do
      socket
      |> LiveStash.reset_stash()
      |> start_new_game()
      |> then(&{:noreply, &1})
    end

# `stash_assigns`

```elixir
@spec stash_assigns(socket :: Phoenix.LiveView.Socket.t(), keys :: [atom()]) ::
  Phoenix.LiveView.Socket.t()
```

Stashes the specified assigns from `socket.assigns`.

Every key must be an atom and should exist in `socket.assigns`.
Call this after assign updates to keep persisted state in sync.

## Examples
    def handle_event("increment", _, socket) do
      socket
      |> assign(:count, socket.assigns.count + 1)
      |> LiveStash.stash_assigns([:count])
      |> then(&{:noreply, &1})  end

---

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