-module(sprocket). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([start/2, handle_client_message/2, shutdown/1, render/2, humanize_error/1, client_message_decoder/0, encode_runtime_message/1]). -export_type([sprocket/0, sprocket_error/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. -type sprocket() :: {sprocket, gleam@erlang@process:subject(sprocket@runtime:message())}. -type sprocket_error() :: runtime_start_error. -file("src/sprocket.gleam", 30). ?DOC(" Starts a new Sprocket runtime with the given element and event dispatcher.\n"). -spec start( sprocket@internal@context:element(), fun((sprocket@runtime:runtime_message()) -> {ok, nil} | {error, nil}) ) -> {ok, sprocket()} | {error, sprocket_error()}. start(El, Dispatch) -> case sprocket@runtime:start(El, Dispatch) of {ok, R} -> sprocket@runtime:render_update(R), {ok, {sprocket, R}}; {error, _} -> {error, runtime_start_error} end. -file("src/sprocket.gleam", 48). ?DOC(" Handles a client message by passing it to the runtime.\n"). -spec handle_client_message(sprocket(), sprocket@runtime:client_message()) -> nil. handle_client_message(Spkt, Msg) -> sprocket@runtime:handle_client_message(erlang:element(2, Spkt), Msg). -file("src/sprocket.gleam", 53). ?DOC(" Shuts down the given Sprocket runtime.\n"). -spec shutdown(sprocket()) -> nil. shutdown(Spkt) -> sprocket@runtime:stop(erlang:element(2, Spkt)). -file("src/sprocket.gleam", 58). ?DOC(" Renders the given element as a stateless element using a given renderer.\n"). -spec render(sprocket@internal@context:element(), sprocket@render:renderer(LUA)) -> LUA. render(El, R) -> sprocket@render:renderer( R, fun(Render) -> _assert_subject = begin _pipe = ids@cuid:start(), gleam@result:map_error( _pipe, fun(Error) -> sprocket@internal@logger:error( <<"render.render: Failed to start a cuid channel"/utf8>> ), Error end ) end, {ok, Cuid_channel} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, value => _assert_fail, module => <<"sprocket"/utf8>>, function => <<"render"/utf8>>, line => 63}) end, Dispatch_client_hook_event = fun(_, _, _) -> nil end, Trigger_reconciliation = fun() -> nil end, Update_hook = fun(_, _) -> nil end, Ctx = sprocket@internal@context:new( El, Cuid_channel, Dispatch_client_hook_event, Trigger_reconciliation, Update_hook ), {reconciled_result, _, Reconciled} = sprocket@internal@reconcilers@recursive:reconcile( Ctx, El, none, none ), Render(Reconciled) end ). -file("src/sprocket.gleam", 90). ?DOC(" Returns a human-readable error message for the given SprocketError.\n"). -spec humanize_error(sprocket_error()) -> binary(). humanize_error(Error) -> case Error of runtime_start_error -> <<"Failed to start runtime"/utf8>> end. -file("src/sprocket.gleam", 107). ?DOC(" Decoder for inbound client hook events.\n"). -spec inbound_client_hook_event_decoder() -> gleam@dynamic@decode:decoder(sprocket@runtime:client_message()). inbound_client_hook_event_decoder() -> gleam@dynamic@decode:field( <<"id"/utf8>>, {decoder, fun gleam@dynamic@decode:decode_string/1}, fun(Element_id) -> gleam@dynamic@decode:field( <<"hook"/utf8>>, {decoder, fun gleam@dynamic@decode:decode_string/1}, fun(Hook) -> gleam@dynamic@decode:field( <<"kind"/utf8>>, {decoder, fun gleam@dynamic@decode:decode_string/1}, fun(Kind) -> gleam@dynamic@decode:optional_field( <<"payload"/utf8>>, none, gleam@dynamic@decode:optional( {decoder, fun gleam@dynamic@decode:decode_dynamic/1} ), fun(Payload) -> gleam@dynamic@decode:success( {inbound_client_hook_event, Element_id, Hook, Kind, Payload} ) end ) end ) end ) end ). -file("src/sprocket.gleam", 120). -spec client_event_decoder() -> gleam@dynamic@decode:decoder(sprocket@runtime:client_message()). client_event_decoder() -> gleam@dynamic@decode:field( <<"id"/utf8>>, {decoder, fun gleam@dynamic@decode:decode_string/1}, fun(Element_id) -> gleam@dynamic@decode:field( <<"kind"/utf8>>, {decoder, fun gleam@dynamic@decode:decode_string/1}, fun(Kind) -> gleam@dynamic@decode:optional_field( <<"payload"/utf8>>, gleam_stdlib:identity(nil), {decoder, fun gleam@dynamic@decode:decode_dynamic/1}, fun(Payload) -> gleam@dynamic@decode:success( {client_event, Element_id, Kind, Payload} ) end ) end ) end ). -file("src/sprocket.gleam", 97). ?DOC(" Decoder for client messages.\n"). -spec client_message_decoder() -> gleam@dynamic@decode:decoder(sprocket@runtime:client_message()). client_message_decoder() -> gleam@dynamic@decode:then( gleam@dynamic@decode:at( [0], {decoder, fun gleam@dynamic@decode:decode_string/1} ), fun(Message_type) -> case Message_type of <<"hook"/utf8>> -> gleam@dynamic@decode:at( [1], inbound_client_hook_event_decoder() ); _ -> gleam@dynamic@decode:at([1], client_event_decoder()) end end ). -file("src/sprocket.gleam", 176). -spec payload_decoder() -> gleam@dynamic@decode:decoder(gleam@json:json()). payload_decoder() -> gleam@dynamic@decode:recursive( fun() -> gleam@dynamic@decode:one_of( begin _pipe = {decoder, fun gleam@dynamic@decode:decode_string/1}, gleam@dynamic@decode:map(_pipe, fun gleam@json:string/1) end, [begin _pipe@1 = {decoder, fun gleam@dynamic@decode:decode_int/1}, gleam@dynamic@decode:map(_pipe@1, fun gleam@json:int/1) end, begin _pipe@2 = {decoder, fun gleam@dynamic@decode:decode_float/1}, gleam@dynamic@decode:map( _pipe@2, fun gleam@json:float/1 ) end, begin _pipe@3 = {decoder, fun gleam@dynamic@decode:decode_bool/1}, gleam@dynamic@decode:map(_pipe@3, fun gleam@json:bool/1) end, begin _pipe@4 = gleam@dynamic@decode:list(payload_decoder()), gleam@dynamic@decode:map( _pipe@4, fun gleam@json:preprocessed_array/1 ) end, begin _pipe@5 = gleam@dynamic@decode:dict( {decoder, fun gleam@dynamic@decode:decode_string/1}, payload_decoder() ), gleam@dynamic@decode:map(_pipe@5, fun(D) -> _pipe@6 = D, _pipe@7 = maps:to_list(_pipe@6), gleam@json:object(_pipe@7) end) end] ) end ). -file("src/sprocket.gleam", 172). -spec encode_payload(gleam@dynamic:dynamic_()) -> {ok, gleam@json:json()} | {error, list(gleam@dynamic@decode:decode_error())}. encode_payload(Payload) -> gleam@dynamic@decode:run(Payload, payload_decoder()). -file("src/sprocket.gleam", 133). ?DOC(" Encodes a runtime message as JSON.\n"). -spec encode_runtime_message(sprocket@runtime:runtime_message()) -> gleam@json:json(). encode_runtime_message(Event) -> case Event of {full_update, Update} -> sprocket@render:renderer( sprocket@renderers@json:json_renderer(), fun(Render_json) -> gleam@json:preprocessed_array( [gleam@json:string(<<"ok"/utf8>>), Render_json(Update)] ) end ); {patch_update, P} -> gleam@json:preprocessed_array( [gleam@json:string(<<"update"/utf8>>), sprocket@internal@patch:patch_to_json(P)] ); {outbound_client_hook_event, Id, Hook, Kind, Payload} -> Payload_json = begin _pipe = Payload, _pipe@1 = gleam@option:map(_pipe, fun encode_payload/1), _pipe@2 = gleam@option:map( _pipe@1, fun gleam@option:from_result/1 ), gleam@option:flatten(_pipe@2) end, gleam@json:preprocessed_array( [gleam@json:string(<<"hook"/utf8>>), case Payload_json of {some, Payload_json@1} -> gleam@json:object( [{<<"id"/utf8>>, gleam@json:string(Id)}, {<<"hook"/utf8>>, gleam@json:string(Hook)}, {<<"kind"/utf8>>, gleam@json:string(Kind)}, {<<"payload"/utf8>>, Payload_json@1}] ); none -> gleam@json:object( [{<<"id"/utf8>>, gleam@json:string(Id)}, {<<"hook"/utf8>>, gleam@json:string(Hook)}, {<<"kind"/utf8>>, gleam@json:string(Kind)}] ) end] ) end.