# `Filament.Observable.GenServer`

Macro that makes a GenServer observable by Filament components.

`use Filament.Observable.GenServer` injects:

  - `handle_call({:filament_subscribe, subscriber}, from, state)` —
    subscriber registration; calls `handle_subscribe/2` (overridable)
  - `handle_cast({:filament_remove_projection, owner_pid, proj_key}, state)` —
    projection removal; auto-unsubscribes when the last projection is removed
  - `handle_info({:DOWN, ref, :process, pid, reason}, state)` —
    automatic subscriber cleanup when a LiveView process terminates
  - `notify_observers/1` — call this from your handlers whenever state changes
    to push raw state to all subscribed components

Subscribers are keyed by `owner_pid`. All fibers within the same LiveView that
subscribe to the same server share one subscriber entry. Each fiber registers a
named projection key; `notify_observers/1` sends one
`{:filament_observable_updates, [{fiber_id, slot_index, raw_state}]}` message
per subscriber whenever the raw state changes (change-or-bust at subscriber level).
Projection fns run client-side on each re-render, so closures over local component
state (filters, selections, etc.) always see the current value.

## Example

    defmodule MyApp.Counter do
      use Filament.Observable.GenServer

      def start_link(opts \\ []) do
        GenServer.start_link(__MODULE__, 0, name: Keyword.get(opts, :name, __MODULE__))
      end

      @impl GenServer
      def init(initial), do: {:ok, initial}

      @impl Filament.Observable
      def handle_subscribe(_subscriber, state) do
        {:ok, state, state}
      end

      @impl GenServer
      def handle_call(:increment, _from, count) do
        new_count = count + 1
        notify_observers(new_count)
        {:reply, new_count, new_count}
      end
    end

---

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