AshUi (ash_ui v0.1.0)

Copy Markdown View Source

Static AshUi extension and runtime surface.

AshUi page resources are defined as normal Ash.Resource modules with extensions: [AshUi], compiled through Spark/Ash, and consumed through persisted compile-time contracts at runtime.

Application-authored state, reads, and behavior remain ordinary Ash attributes, relationships, calculations, and actions.

Summary

Functions

Builds the record a render(Child, input) child renders from — the ONE public construction path hosts use: an embedded child casts its input through its create action (instances pass through untouched); a store-backed child resolves its mounted row.

Casts raw maps (an engine/boundary result) into a list of embedded value-resource structs — the ONE sanctioned way raw data enters a AshUi read model. Raises a located error naming the row index and the failing field, so shape drift surfaces at the boundary instead of as a nil deep in a view.

Formats one original dispatch error for a host-owned page error surface.

The original Ash error objects of a failed dispatch, as a flat list — the public error-surface contract for bridge adapters.

Reloads a resource through its declared session identity.

Reloads exactly one relationship path on an already-loaded record.

The :view calculation's derived load statement — the relationships and nested loads the view reads. Hosts load records through this before any render; it is the same dependency set Ash.calculate(record, :view) loads through the calculation's load/3.

Types

definition_input()

@type definition_input() :: module()

Functions

blueprint!(module)

@spec blueprint!(module()) :: map()

build_child_record(resource, input, opts \\ [])

@spec build_child_record(module(), term(), keyword()) ::
  {:ok, struct()} | {:error, term()}

Builds the record a render(Child, input) child renders from — the ONE public construction path hosts use: an embedded child casts its input through its create action (instances pass through untouched); a store-backed child resolves its mounted row.

cast_rows(module, rows)

Casts raw maps (an engine/boundary result) into a list of embedded value-resource structs — the ONE sanctioned way raw data enters a AshUi read model. Raises a located error naming the row index and the failing field, so shape drift surfaces at the boundary instead of as a nil deep in a view.

{:ok, entries} = AshUi.cast_rows(TreeEntry, raw_maps)
entries = AshUi.cast_rows!(TreeEntry, raw_maps)

cast_rows!(module, rows)

compile!(input, opts \\ [])

dispatch_error_message(error)

@spec dispatch_error_message(term()) :: String.t()

Formats one original dispatch error for a host-owned page error surface.

Field errors include their field name; fieldless errors preserve the user-facing Ash message.

dispatch_errors(reason)

The original Ash error objects of a failed dispatch, as a flat list — the public error-surface contract for bridge adapters.

reload(record, opts \\ [])

@spec reload(struct(), keyword()) :: {:ok, struct()} | {:error, term()}

Reloads a resource through its declared session identity.

Entity UI resources do not need a synthetic primary key: the ordinary Ash identity containing :session_id is their stable lookup contract. Resources without such an identity fall back to their primary key.

reload_scope(record, path, opts)

@spec reload_scope(struct(), :root | [atom()], keyword()) ::
  {:ok, struct()} | {:error, term()}

Reloads exactly one relationship path on an already-loaded record.

Notification adapters use this when their compile-derived subscription identifies the affected relationship. :root retains the ordinary durable row reload contract; a path such as [:artist, :albums] refreshes only that relationship branch and preserves all unrelated loaded view fields.

render(resource, input, opts \\ [])

@spec render(module(), map(), keyword()) ::
  {:ok, AshUi.RenderTree.t()} | {:error, term()}

render!(resource, input, opts \\ [])

@spec render!(module(), map(), keyword()) :: AshUi.RenderTree.t()

route(body)

(macro)

routes(body)

(macro)

verify_deferred!(modules)

@spec verify_deferred!(module() | [module()]) :: :ok

view_load(resource, view \\ :view)

@spec view_load(module(), atom()) :: list()

The :view calculation's derived load statement — the relationships and nested loads the view reads. Hosts load records through this before any render; it is the same dependency set Ash.calculate(record, :view) loads through the calculation's load/3.