# `BaileysEx.Signal.Store`
[🔗](https://github.com/jeffhuen/baileys_ex/blob/main/lib/baileys_ex/signal/store.ex#L1)

Runtime-backed Signal key store boundary aligned with Baileys' `keys` contract.

The store exposes three core operations:

- `get/3` for keyed reads by logical family
- `set/2` for batched updates and deletions (`nil` removes an entry)
- `transaction/3` for per-key serialized work through an explicit
  transaction-scoped store handle

Custom store modules must pass that transaction-scoped handle into the
closure:

    transaction(ref, "session:alice", fn tx_ref ->
      existing = get(tx_ref, :session, ["alice.0"])
      :ok = set(tx_ref, %{session: %{"alice.0" => updated}})
      existing
    end)

Concrete persistence remains swappable. The default in-memory runtime
implementation can be replaced with file/ETS/DB-backed variants without
changing repository consumers.

# `data_entries`

```elixir
@type data_entries() :: %{optional(String.t()) =&gt; data_value()}
```

# `data_set`

```elixir
@type data_set() :: %{
  optional(data_type()) =&gt; %{optional(String.t()) =&gt; data_value() | nil}
}
```

# `data_type`

```elixir
@type data_type() ::
  :session
  | :&quot;pre-key&quot;
  | :&quot;sender-key&quot;
  | :&quot;sender-key-memory&quot;
  | :&quot;app-state-sync-key&quot;
  | :&quot;app-state-sync-version&quot;
  | :&quot;lid-mapping&quot;
  | :&quot;device-list&quot;
  | :tctoken
  | :&quot;identity-key&quot;
```

Logical key families matching Baileys' Signal store.

# `data_value`

```elixir
@type data_value() ::
  binary()
  | [String.t()]
  | %{optional(String.t()) =&gt; boolean()}
  | %{:token =&gt; binary(), optional(:timestamp) =&gt; String.t()}
  | %{public: binary(), private: binary()}
  | term()
```

One value written under a logical key family.

# `start_result`

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

# `t`

```elixir
@type t() :: %BaileysEx.Signal.Store{module: module(), ref: term()}
```

Store handle passed to repository and helper modules.

# `clear`

```elixir
@callback clear(term()) :: :ok
```

# `get`

```elixir
@callback get(term(), data_type(), [String.t()]) :: data_entries()
```

# `in_transaction?`

```elixir
@callback in_transaction?(term()) :: boolean()
```

# `set`

```elixir
@callback set(term(), data_set()) :: :ok
```

# `start_link`

```elixir
@callback start_link(keyword()) :: start_result()
```

# `transaction`

```elixir
@callback transaction(term(), String.t(), (term() -&gt; result)) :: result when result: var
```

# `wrap`

```elixir
@callback wrap(term()) :: term()
```

# `clear`

```elixir
@spec clear(t()) :: :ok
```

Flushes the data store completely.

# `get`

```elixir
@spec get(t(), data_type(), [String.t()]) :: data_entries()
```

Extracts values from the store sequentially resolving cache items.

# `in_transaction?`

```elixir
@spec in_transaction?(t()) :: boolean()
```

Examines if identical transaction processes cover the ongoing context stack.

# `set`

```elixir
@spec set(t(), data_set()) :: :ok
```

Persists an explicitly typed data set definition back to the store.

# `start_link`

```elixir
@spec start_link(keyword()) :: {:ok, t()} | :ignore | {:error, term()}
```

Initializes and starts the underlying data store process/pool.

# `transaction`

```elixir
@spec transaction(t(), String.t(), (t() -&gt; result)) :: result when result: var
```

Executes work inside of a logically consistent mutex-isolated transaction.

The callback receives a transaction-scoped store handle. Reads and writes
that should participate in the transaction must use that handle, not the
outer non-transactional store handle.

# `wrap_running`

```elixir
@spec wrap_running(t() | {module(), term()} | term() | nil) :: t() | nil
```

Resolve a running store process or `{module, server}` tuple into a wrapped
`BaileysEx.Signal.Store` handle.

---

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