arizona_effect (arizona v0.4.0)
View SourceNeutral 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
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.
-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.
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.
-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).