# `Xitdb`
[🔗](https://github.com/boxxxie/xitdb-elixir/blob/v1.0.1/lib/xitdb.ex#L1)

Idiomatic Elixir client and Odin NIF wrapper for [`xitdb`](https://github.com/xit-vcs/xitdb),
an embeddable, immutable, append-only database with persistent structural sharing.

`Xitdb` exposes database moments as lazy `%Xitdb.Cursor{}` handles that implement
Elixir's `Access`, `Enumerable`, and `Inspect` protocols—allowing you to navigate
and query on-disk data structures (`Hash_Map`, `Counted_Hash_Map`, `Sorted_Map`,
`Array_List`, `Linked_Array_List`, and sets) just like standard Elixir maps and lists.

# `t`

```elixir
@type t() :: %Xitdb{
  backend: :memory | :file | :buffered_file,
  db_ref: reference(),
  hash: :sha1 | :sha256,
  path: String.t()
}
```

# `array_list`

```elixir
@spec array_list(list()) :: Xitdb.Collection.t()
```

Wraps `list` to be stored as a 16-way Radix Trie (`Array_List`).

# `as_of`

```elixir
@spec as_of(t(), integer()) :: Xitdb.Cursor.t()
```

Returns a lazy `%Xitdb.Cursor{}` pinned to historical `moment_index` (`0..N-1`, or negative from end).

# `at`

# `close`

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

Flushes and closes the underlying `xitdb` storage handle.

# `compact`

```elixir
@spec compact(t(), keyword()) :: {:ok, t()} | {:error, Xitdb.Error.t()}
```

Compacts `db` into a new database keeping only the latest committed moment and deduplicating
reachable slots.

# `compact!`

```elixir
@spec compact!(t(), keyword()) :: t()
```

Same as `compact/2`, but raises `Xitdb.Error` on failure.

# `counted_map`

```elixir
@spec counted_map(Enumerable.t()) :: Xitdb.Collection.t()
```

Wraps `map` to be stored as a `Counted_Hash_Map` with $O(1)$ `Enum.count/1`.

# `counted_set`

```elixir
@spec counted_set(Enumerable.t()) :: Xitdb.Collection.t()
```

Wraps `members` to be stored as a `Counted_Hash_Set` with $O(1)$ `Enum.count/1`.

# `datalog`
*macro* 

# `db`

```elixir
@spec db(t()) :: Xitdb.Cursor.t()
```

Returns a lazy `%Xitdb.Cursor{}` pointing to the latest committed moment (`-1`).

# `delete_at`

```elixir
@spec delete_at(Xitdb.Cursor.t(), String.t() | [term()], integer()) ::
  Xitdb.Cursor.t()
```

Stages an $O(\log N)$ removal from a `Linked_Array_List` at `path_or_selector` and `index`
on a root `%Xitdb.Cursor{}` inside `Xitdb.transact/2`.

# `diff_moments`

```elixir
@spec diff_moments(t(), integer(), integer()) ::
  {:ok, [map()]} | {:error, Xitdb.Error.t()}
```

Computes the structural diff between `moment_a` and `moment_b`, skipping unchanged
subtrees in $O(1)$ via 9-byte `Slot` equality.

# `fork`

```elixir
@spec fork(Xitdb.Cursor.t(), String.t(), String.t()) :: Xitdb.Cursor.t()
```

Stages an $O(1)$ zero-copy structural clone (`tx_fork`) from `from_selector` to `to_selector`.

# `hash_map`

```elixir
@spec hash_map(Enumerable.t()) :: Xitdb.Collection.t()
```

Wraps `map` to be stored as an uncounted 16-way HAMT (`Tag.Hash_Map`).

# `hash_set`

```elixir
@spec hash_set(Enumerable.t()) :: Xitdb.Collection.t()
```

Wraps `members` to be stored as a 16-way HAMT `Hash_Set`.

# `history_of`

```elixir
@spec history_of(t(), String.t()) :: {:ok, [map()]} | {:error, Xitdb.Error.t()}
```

Returns the historical lineage of `selector` across all moments where its `Slot` changed.

# `info`

```elixir
@spec info(t()) :: {:ok, map()} | {:error, Xitdb.Error.t()}
```

Returns database metadata (`%{moment_count: integer(), file_size: integer()}`).

# `info!`

```elixir
@spec info!(t()) :: map()
```

Same as `info/1`, but raises `Xitdb.Error` on failure.

# `insert_at`

```elixir
@spec insert_at(Xitdb.Cursor.t(), String.t() | [term()], integer(), term()) ::
  Xitdb.Cursor.t()
```

Stages an $O(\log N)$ insertion into a `Linked_Array_List` at `path_or_selector` and `index`
on a root `%Xitdb.Cursor{}` inside `Xitdb.transact/2`.

`path_or_selector` can be a selector string (`path(users[id].queue)`) or a list of keys /
typed `{kind, key}` steps (`[{:counted, "users"}, "alice", "queue"]`).

# `linked_list`

```elixir
@spec linked_list(list()) :: Xitdb.Collection.t()
```

Wraps `list` to be stored as a count-augmented B-Tree (`Linked_Array_List`).

# `materialize`

```elixir
@spec materialize(t() | Xitdb.Cursor.t() | term()) :: term()
```

Eagerly materializes a `%Xitdb.Cursor{}` (or `%Xitdb{}` database handle) into native
Elixir maps (`%{}`), lists (`[]`), sets (`MapSet.t()`), and scalars.

# `moment_count`

```elixir
@spec moment_count(t()) :: non_neg_integer()
```

Returns the number of committed historical moments in `db`.

# `open`

```elixir
@spec open(keyword()) :: {:ok, t()} | {:error, Xitdb.Error.t()}
```

Opens a `Xitdb` database instance.

## Options
* `:backend` - Storage backend (`:memory`, `:file`, or `:buffered_file`). The default value is `:memory`.

* `:path` (`t:String.t/0`) - Filesystem path for `:file` or `:buffered_file` backends. The default value is `""`.

* `:hash` - Cryptographic digest algorithm for HAMT keys (`:sha1` or `:sha256`). The default value is `:sha1`.

# `open!`

```elixir
@spec open!(keyword()) :: t()
```

Same as `open/1`, but raises `Xitdb.Error` on failure.

# `path`
*macro* 

# `pull`

```elixir
@spec pull(t() | Xitdb.Cursor.t(), Xitdb.Pull.pattern()) ::
  {:ok, term()} | {:error, Xitdb.Error.t()}
```

Executes a Datomic-style Pull projection against a `%Xitdb.Cursor{}` or `%Xitdb{}` handle.

Accepts either a raw Pull pattern string (`"{username, age, todos[0..2], profile{city}}"`)
or a structural Elixir list (`[:username, :age, todos: 0..2, profile: [:city]]`).

# `pull!`

```elixir
@spec pull!(t() | Xitdb.Cursor.t(), Xitdb.Pull.pattern()) :: term()
```

Same as `pull/2`, but raises `Xitdb.Error` on failure.

# `pull_pattern`
*macro* 

# `query`

```elixir
@spec query(t() | Xitdb.Cursor.t(), String.t(), keyword()) ::
  {:ok, %{vars: [String.t()], rows: [[term()]]}} | {:error, Xitdb.Error.t()}
```

Executes a Datalog query (`~q"find ?e, ?name where ..."`) against `db` or a `%Xitdb.Cursor{}`.

# `query!`

```elixir
@spec query!(t() | Xitdb.Cursor.t(), String.t(), keyword()) :: %{
  vars: [String.t()],
  rows: [[term()]]
}
```

Same as `query/3`, but raises `Xitdb.Error` on failure.

# `select`

```elixir
@spec select(t() | Xitdb.Cursor.t(), String.t()) ::
  {:ok, term()} | {:error, Xitdb.Error.t()}
```

Resolves a canonical `xitdb` selector string (`~x|.users["101"].todos[1]|`) against `db` or a `%Xitdb.Cursor{}`.

# `select!`

```elixir
@spec select!(t() | Xitdb.Cursor.t(), String.t()) :: term()
```

Same as `select/2`, but raises `Xitdb.Error` on failure.

# `sorted_map`

```elixir
@spec sorted_map(Enumerable.t()) :: Xitdb.Collection.t()
```

Wraps `map` to be stored as a lexicographically ordered B+Tree (`Sorted_Map`).

# `sorted_set`

```elixir
@spec sorted_set(Enumerable.t()) :: Xitdb.Collection.t()
```

Wraps `members` to be stored as a lexicographically ordered B+Tree `Sorted_Set`.

# `sync`

```elixir
@spec sync(t()) :: :ok | {:error, Xitdb.Error.t()}
```

Synchronizes buffered writes to disk.

# `transact`

```elixir
@spec transact(
  t(),
  map() | (Xitdb.Cursor.t() -&gt; Xitdb.Cursor.t() | {:abort, term()}),
  keyword()
) ::
  {:ok, t()} | {:error, Xitdb.Error.t()}
```

Executes an atomic transaction committing a new moment to `db`.

Accepts either:
- A map of top-level keys/subtrees (`Xitdb.transact(db, %{"users" => ...}, opts)`), or
- A 1-arity callback receiving the root `%Xitdb.Cursor{}` (`Xitdb.transact(db, fn root -> put_in(root["a"]["b"], 1) end)`).

# `transact!`

```elixir
@spec transact!(t(), map() | (Xitdb.Cursor.t() -&gt; Xitdb.Cursor.t()), keyword()) :: t()
```

Same as `transact/3`, but raises `Xitdb.Error` on failure.

# `transact_ops`

```elixir
@spec transact_ops(t(), list(), keyword()) :: {:ok, t()} | {:error, Xitdb.Error.t()}
```

Executes a list of low-level transaction tuples (`{:put, path, val}`, `{:insert, path, idx, val}`, etc.)
in a single atomic NIF transaction commit.

# `tx`
*macro* 

# `tx`
*macro* 

# `tx!`
*macro* 

# `tx!`
*macro* 

---

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