arizona_effect (arizona v0.4.0)

View Source

Neutral wire format and encoders for client effect commands.

An effect is a cmd/0 tuple {arizona_effect, [OpCode | Args]} that a client runtime executes. The tuple shape and op codes (include/arizona_effect.hrl) are the same on every client; only the builders are per platform (arizona_js for the web, arizona_android for native, ...), so neither platform owns the representation. This module is the shared plumbing: the tag, the cmd/0 type, and the two encoders.

encode/1 serializes to JSON and HTML-escapes &, ", < for embedding in an HTML attribute (the web path). encode_json/1 serializes to raw JSON for clients that embed the command as a JSON value (the native path).

These encoders serve commands that reach a client as data -- an event attribute or prop, a controller response -- never the effects a live handler returns, which the socket frames itself. So a navigate/patch carrying a flash opt is refused here with {flash_outside_live_effect, navigate | patch}: the socket carries that flash in-process to the navigation that follows its effect, and nothing would carry it from a client that received it as data -- the message would be lost silently, its content shipped to the page.

Summary

Functions

json_value/1 without the flash refusal: the bare command (or the flattened list of them) for a builder that wraps commands -- transition, on_key, a fetch's on_error -- whose result may still be a live handler's effect, where the socket carries a navigate's flash. The refusal runs when the wrapper itself is encoded as data, and sees inside it (wrapped/1).

Encodes a command (or list of commands) as an HTML-attribute-safe binary: JSON with &, ", and < escaped to their HTML entity equivalents.

Serializes a command (or list of commands) to raw JSON, without the HTML attribute escaping encode/1 applies. Used by non-HTML backends (native) that embed the command as a JSON value.

Formats the errors this module raises with an error_info annotation. Picked up by erl_error:format_exception/3.

The command (or list of commands) as the JSON term it serializes to: [OpCode | Args], or a list of those. A wire that JSON-encodes its values itself (a diff op, the native hydration payload) carries this, so the client receives the command as an array rather than a string of one.

The commands a bare command ([OpCode | Args], as json_value/1 yields) wraps -- a transition, an on_key, or a fetch's on_error -- as a list, with when they run (now when the command does, deferred later, if ever) and a fun that rebuilds the wrapper around a replacement list. none for any other command. The one list of wrapper shapes, shared by every walk that must see inside them (arizona_socket's flash capture, this module's flash refusal).

Types

cmd()

-nominal cmd() :: {arizona_effect, list()}.

cmds()

-type cmds() :: [cmd() | cmds()].

Functions

bare(Cmds)

-spec bare(Cmds) -> list() when Cmds :: cmd() | cmds().

json_value/1 without the flash refusal: the bare command (or the flattened list of them) for a builder that wraps commands -- transition, on_key, a fetch's on_error -- whose result may still be a live handler's effect, where the socket carries a navigate's flash. The refusal runs when the wrapper itself is encoded as data, and sees inside it (wrapped/1).

encode(Cmds)

-spec encode(Cmds) -> binary() when Cmds :: cmd() | cmds().

Encodes a command (or list of commands) as an HTML-attribute-safe binary: JSON with &, ", and < escaped to their HTML entity equivalents.

encode_json(Cmds)

-spec encode_json(Cmds) -> binary() when Cmds :: cmd() | cmds().

Serializes a command (or list of commands) to raw JSON, without the HTML attribute escaping encode/1 applies. Used by non-HTML backends (native) that embed the command as a JSON value.

format_error(Reason, Stacktrace)

-spec format_error(Reason, Stacktrace) -> ErrorInfo
                      when
                          Reason :: term(), Stacktrace :: [tuple()], ErrorInfo :: #{general := iolist()}.

Formats the errors this module raises with an error_info annotation. Picked up by erl_error:format_exception/3.

json_value(Cmds)

-spec json_value(Cmds) -> list() when Cmds :: cmd() | cmds().

The command (or list of commands) as the JSON term it serializes to: [OpCode | Args], or a list of those. A wire that JSON-encodes its values itself (a diff op, the native hydration payload) carries this, so the client receives the command as an array rather than a string of one.

A list may nest, and [] stands for no command: the list is flattened in order and empty items dropped, so a conditional item (case ... of true -> arizona_js:hide(Sel); false -> [] end) needs no filtering at the call site. Any other item fails with function_clause.

wrapped(Cmd)

-spec wrapped(Cmd) -> {now | deferred, [list()], fun(([list()]) -> list())} | none when Cmd :: list().

The commands a bare command ([OpCode | Args], as json_value/1 yields) wraps -- a transition, an on_key, or a fetch's on_error -- as a list, with when they run (now when the command does, deferred later, if ever) and a fun that rebuilds the wrapper around a replacement list. none for any other command. The one list of wrapper shapes, shared by every walk that must see inside them (arizona_socket's flash capture, this module's flash refusal).