# `DrinkMeAlice.Ash.DataLayer`

An Ash data layer over a supervised `DrinkMeAlice.Conn`.

    use Ash.Resource,
      domain: MyApp.Crew,
      data_layer: DrinkMeAlice.Ash.DataLayer

    surrealdb do
      conn MyApp.Surreal
      table "mission"
    end

## Storage

The single primary-key attribute (string, UUID or integer) is the
record id (`mission:⟨pk⟩`); every other attribute is a field.
Schema DDL comes from `DrinkMeAlice.Ash.Schema`. Types map per
`DrinkMeAlice.Ash.Codec`.

## Writes

Each create/update/destroy is one `DrinkMeAlice.Tx` transaction, so
the outcome is honest:

- a duplicate primary key or a violated identity index →
  `Ash.Error.Changes.InvalidChanges` ("has already been taken");
- an update/destroy whose record is gone or fails the changeset
  filter → `Ash.Error.Changes.StaleRecord` (checked inside the tx);
- a lost or inconclusive reply → `DrinkMeAlice.Ash.OutcomeUnknown`
  — the write MAY have committed; reconcile by reading;
- a certified non-send → `DrinkMeAlice.Ash.Unavailable`.

## Reads

Filters are pushed down (see `DrinkMeAlice.Ash.Filter`) and sorts
on plain attributes become `ORDER BY`; `limit`/`offset` become
`LIMIT`/`START`. Every read is bounded by `max_rows`: a read that
would exceed it is an error, never a truncated answer.
Relationships load through `in` filters on the destination attribute.

## Not supported (yet)

Transactions across actions, upserts, bulk/atomic/query updates,
aggregates, calculations in the data layer, multitenancy, joins
(`exists`, filters across relationships), and graph edges as Ash
relationships (use `DrinkMeAlice.Graph` directly).

# `conn`

The configured `Conn` name.

# `primary_key!`

The single primary-key attribute name; raises unless exactly one.

# `surrealdb`
*macro* 

# `table`

The table name (validated identifier).

---

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