# `Issho.Engine`
[🔗](https://github.com/hattoriai/issho/blob/v0.1.0/lib/issho/engine.ex#L1)

The model of a document: how its operations apply. Each binding brings
one (Kotoba's text, Hakushi's graph, a map for shared assigns), and the
authority (`Issho.Authority`) runs it.

An engine is pure: no I/O, no clock, no randomness. The same operations
on the same state give the same state on every node, in a test, and in
the browser's twin of the engine. That is also what lets an engine move
to a NIF or to WebAssembly unchanged.

Its state is a map of strings, numbers, booleans, `nil`, lists and maps
with string keys (JSON) when browsers hold the document (they receive
it, and run the engine's twin) or the store saves JSON. A document only
LiveViews and agents hold, kept by no store or a store of terms, can be
any Erlang term: a struct of your own.

Everything outside the engine treats operations as opaque: the authority,
the store, receipts, the journal and the offline queue see only a
transaction's id, its base revision and its author.

## Callbacks

  * `c:name/0` and `c:version/0` tag every stored state, so that a
    document can move to another engine, or a new version, on its own
    schedule.
  * `c:init/2` builds a state from the initial content your policy gives
    (`c:Issho.Policy.document/2`).
  * `c:apply/3` applies one transaction's operations, all or none.
  * `c:validate/2` checks a state and gives its content: what your app
    publishes and the store keeps beside the state (a rendered HTML, a
    graph). Without it, the content is the state.
  * `c:snapshot/1` is what a browser receives when it opens the
    document. Without it, the state.

# `operation`

```elixir
@type operation() :: map()
```

# `state`

```elixir
@type state() :: map()
```

# `apply`

```elixir
@callback apply(state(), [operation()], opts :: keyword()) ::
  {:ok, state()} | {:error, term()}
```

The state after a transaction's operations, all or none. `opts` has the
engine's options and `:author`, the key of the actor who made it.

# `init`

```elixir
@callback init(initial :: term(), opts :: keyword()) :: {:ok, state()} | {:error, term()}
```

A state from the initial content of a document.

# `name`

```elixir
@callback name() :: String.t()
```

The engine's name, stored with every state: `"map"`, `"kotoba"`.

# `snapshot`
*optional* 

```elixir
@callback snapshot(state()) :: map()
```

The state a browser receives when it opens the document.

# `validate`
*optional* 

```elixir
@callback validate(state(), opts :: keyword()) :: {:ok, term()} | {:error, term()}
```

Checks a state and gives its content.

# `version`

```elixir
@callback version() :: pos_integer()
```

The version of the engine's state and operations.

---

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