# `OpenUI.Runtime`
[🔗](https://github.com/ideia4it/openui/blob/v0.1.1/lib/openui/runtime.ex#L1)

A rendered program as a pure value: its state store, form fields, query
results and mutations, with the interactions of language.md, sections 5
and 6.

Functions that may cause something outside the program to happen return
`{runtime, effects}`. The host runs the effects and reports back:

  * `{:emit, %OpenUI.Event{}}`: an action for the host or the model;
  * `{:run_query, query_id, tool, args}`: call the tool, then
    `query_result/4`;
  * `{:run_mutation, run_ref, tool, args}`: call the tool, then
    `mutation_result/3`;
  * `{:schedule_refresh, query_id, seconds}`: call `refresh/2` later. A new one for
    the same query replaces the pending one: keep one timer per query.

Which components are fields and which give a form name to their subtree is
up to each platform (prompt.md, section 2.6), so the runtime takes it as
options:

    OpenUI.Runtime.new(MyApp.Library,
      fields: %{"Input" => [name: "name", type: "input"]},
      forms: %{"Form" => "name"}
    )

A field option may add `rules: "rules"`, the prop holding its validation
rules (`"rules"` by default).

# `effect`

```elixir
@type effect() ::
  {:emit, OpenUI.Event.t()}
  | {:run_query, String.t(), String.t(), map()}
  | {:run_mutation, reference(), String.t(), map()}
  | {:schedule_refresh, String.t(), number()}
```

# `t`

```elixir
@type t() :: %OpenUI.Runtime{
  elements: term(),
  emitted_errors: term(),
  field_errors: term(),
  fields: term(),
  finished?: term(),
  forms: term(),
  library: term(),
  mutations: term(),
  pristine: term(),
  program: term(),
  queries: term(),
  render_errors: term(),
  runs: term(),
  store: term(),
  tree: term()
}
```

# `field_error`

```elixir
@spec field_error(t(), String.t()) :: String.t() | nil
```

The rule a field failed at the latest submit, or `nil`.

# `field_value`

```elixir
@spec field_value(t(), String.t()) :: term()
```

The current value of a field element: its bound `$variable`, or its entry
in the form or page state.

# `finish`

```elixir
@spec finish(t()) :: {t(), [effect()]}
```

Marks the end of the stream: every query runs.

# `form_name`

```elixir
@spec form_name(t(), String.t()) :: String.t() | nil
```

The name of the nearest form around an element, or `nil`.

# `input`

```elixir
@spec input(t(), String.t(), term()) :: {t(), [effect()]}
```

The person changed a field. A bound prop writes its `$variable`; a field
without a binding writes into its form, or the page when it has none.

# `load`

```elixir
@spec load(t(), OpenUI.Program.t()) :: {t(), [effect()]}
```

Loads a program, from a stream frame or an edit. Declared defaults apply to
state the person has not changed; no key is ever deleted. Nothing runs
until `finish/1`.

# `mutation_result`

```elixir
@spec mutation_result(t(), reference(), {:ok, term()} | {:error, term()}) ::
  {t(), [effect()]}
```

The tool answered a mutation started by `{:run_mutation, run_ref, ...}`.
On success the rest of its action plan runs; on failure it stops.

# `new`

```elixir
@spec new(OpenUI.Library.t() | module(), keyword()) :: t()
```

Starts a runtime. Options: `:fields`, `:forms` and `:state`, the state a
host persisted earlier, applied over the program's defaults.

# `query_result`

```elixir
@spec query_result(t(), String.t(), map(), {:ok, term()} | {:error, term()}) ::
  {t(), [effect()]}
```

The tool answered a query. A result for arguments that are no longer the
query's current ones is discarded. `{:error, {:tool_not_found, names}}`
reports `tool-not-found` with the available names; any other error
reports `tool-error`. Either way the query keeps its last good data.

# `query_status`

```elixir
@spec query_status(t()) :: %{
  loading?: boolean(),
  refetching?: boolean(),
  errors: [OpenUI.Error.t()]
}
```

Fetch state of the queries, for a loading indicator and error display.

# `refresh`

```elixir
@spec refresh(t(), String.t()) :: {t(), [effect()]}
```

Fetches a query again, as its refresh interval asks.

# `render_errors`

```elixir
@spec render_errors(t()) :: [OpenUI.Error.t()]
```

The errors the latest evaluation reported.

# `restart`

```elixir
@spec restart(t(), map()) :: t()
```

Starts over for a new response in the same place: a new stream, the given
persisted state, no queries or mutations. The errors already reported are
kept, so `take_errors/2` clears them with `[]` (language.md, section 8.3).

# `state`

```elixir
@spec state(t()) :: map()
```

The state store: `$variables` with their values, form names with their
fields, page-level fields at the top, each field as `%{"value",
"componentType"}`. This is what a host persists.

# `take_errors`

```elixir
@spec take_errors(t(), [OpenUI.Error.t()]) ::
  {t(), :unchanged | {:changed, [OpenUI.Error.t()]}}
```

The error list to send to the host, only when it changed since the last
call (language.md, section 8.3). While a stream is open nothing is
reported, and a list left from an earlier stream is cleared with `[]`.
`renderer_errors` are errors the host's renderer adds, such as a component
that raised.

# `tree`

```elixir
@spec tree(t()) :: OpenUI.Element.t() | nil
```

The evaluated tree, with a `key` on every element.

# `trigger`

```elixir
@spec trigger(t(), String.t(), String.t()) :: {t(), [effect()]}
```

Runs the action plan in a prop of an element. Inside a form, a plan that
sends something (`@ToAssistant`, a library action or a mutation) runs only
when every field of the form passes its rules.

---

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