OpenUI.Runtime (OpenUI v0.1.1)

Copy Markdown View Source

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).

Summary

Functions

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

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

Marks the end of the stream: every query runs.

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

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.

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.

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

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

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.

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

Fetches a query again, as its refresh interval asks.

The errors the latest evaluation reported.

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).

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.

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.

The evaluated tree, with a key on every element.

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.

Types

effect()

@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()

@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()
}

Functions

field_error(runtime, key)

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

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

field_value(runtime, key)

@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(runtime)

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

Marks the end of the stream: every query runs.

form_name(runtime, key)

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

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

input(runtime, key, value)

@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(runtime, program)

@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(runtime, run_ref, result)

@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(library, opts \\ [])

@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(runtime, query_id, args, result)

@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(runtime)

@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(runtime, query_id)

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

Fetches a query again, as its refresh interval asks.

render_errors(runtime)

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

The errors the latest evaluation reported.

restart(runtime, state \\ %{})

@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(runtime)

@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(runtime, renderer_errors \\ [])

@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(runtime)

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

The evaluated tree, with a key on every element.

trigger(runtime, key, prop)

@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.