-module(rally@generator@json_rpc_dispatch).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/rally/generator/json_rpc_dispatch.gleam").
-export([to_pascal_case/1, handler_alias/1, endpoint_json_tag/1, closure_param_for_fieldtype/1, json_encoder_for_fieldtype/2, json_response_encode/1, json_handler_call/3, json_dispatch_arm/3, generate_json_dispatch_function_with_prefix/3, generate_json_dispatch_function/2, handler_imports/1]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" JSON-specific RPC dispatch codegen.\n"
"\n"
" Generates dispatch functions that route JSON-encoded RPC calls to\n"
" server_* handlers. Handles JSON response encoding and type registry\n"
" building for the JSON protocol path.\n"
).
-file("src/rally/generator/json_rpc_dispatch.gleam", 17).
-spec to_pascal_case(binary()) -> binary().
to_pascal_case(Name) ->
_pipe = Name,
_pipe@1 = gleam@string:split(_pipe, <<"_"/utf8>>),
_pipe@2 = gleam@list:map(
_pipe@1,
fun(Word) -> case gleam_stdlib:string_pop_grapheme(Word) of
{ok, {First, Rest}} ->
<<(string:uppercase(First))/binary, Rest/binary>>;
{error, nil} ->
Word
end end
),
gleam@string:join(_pipe@2, <<""/utf8>>).
-file("src/rally/generator/json_rpc_dispatch.gleam", 29).
-spec handler_alias(binary()) -> binary().
handler_alias(Module_path) ->
<<(gleam@string:replace(Module_path, <<"/"/utf8>>, <<"_"/utf8>>))/binary,
"_handler"/utf8>>.
-file("src/rally/generator/json_rpc_dispatch.gleam", 33).
-spec endpoint_json_tag(libero@scanner:handler_endpoint()) -> binary().
endpoint_json_tag(Endpoint) ->
{Module_path@1, Type_name@1} = case erlang:element(8, Endpoint) of
{some, {Module_path, Type_name}} ->
{Module_path, Type_name};
_ ->
{erlang:element(2, Endpoint),
to_pascal_case(
<<"server_"/utf8, (erlang:element(3, Endpoint))/binary>>
)}
end,
<<<<Module_path@1/binary, "."/utf8>>/binary, Type_name@1/binary>>.
-file("src/rally/generator/json_rpc_dispatch.gleam", 188).
-spec closure_param_for_fieldtype(libero@field_type:field_type()) -> binary().
closure_param_for_fieldtype(Ft) ->
case Ft of
nil_field ->
<<"_x"/utf8>>;
_ ->
<<"x"/utf8>>
end.
-file("src/rally/generator/json_rpc_dispatch.gleam", 195).
-spec json_encoder_for_fieldtype(libero@field_type:field_type(), binary()) -> binary().
json_encoder_for_fieldtype(Ft, Var) ->
case Ft of
string_field ->
<<<<"json.string("/utf8, Var/binary>>/binary, ")"/utf8>>;
int_field ->
<<<<"json.int("/utf8, Var/binary>>/binary, ")"/utf8>>;
float_field ->
<<<<"json.float("/utf8, Var/binary>>/binary, ")"/utf8>>;
bool_field ->
<<<<"json.bool("/utf8, Var/binary>>/binary, ")"/utf8>>;
nil_field ->
<<"json.null()"/utf8>>;
bit_array_field ->
<<<<"json.string(bit_array.base64_encode("/utf8, Var/binary>>/binary,
", True))"/utf8>>;
{user_type, Module_path, Type_name, _} ->
<<<<<<<<"json_codecs.json_encode_"/utf8,
(libero@walker:qualified_atom_name(
Module_path,
Type_name
))/binary>>/binary,
"("/utf8>>/binary,
Var/binary>>/binary,
")"/utf8>>;
{list_of, Inner} ->
<<<<<<<<"json_codecs.json_encode_gleam__list("/utf8, Var/binary>>/binary,
", fn(x) { "/utf8>>/binary,
(json_encoder_for_fieldtype(Inner, <<"x"/utf8>>))/binary>>/binary,
" })"/utf8>>;
{option_of, Inner@1} ->
<<<<<<<<"json_codecs.json_encode_gleam_option__option("/utf8,
Var/binary>>/binary,
", fn(x) { "/utf8>>/binary,
(json_encoder_for_fieldtype(Inner@1, <<"x"/utf8>>))/binary>>/binary,
" })"/utf8>>;
{result_of, Ok, Err} ->
<<<<<<<<<<<<"json_codecs.json_encode_gleam_result__result("/utf8,
Var/binary>>/binary,
", fn(x) { "/utf8>>/binary,
(json_encoder_for_fieldtype(Ok, <<"x"/utf8>>))/binary>>/binary,
" }, fn(x) { "/utf8>>/binary,
(json_encoder_for_fieldtype(Err, <<"x"/utf8>>))/binary>>/binary,
" })"/utf8>>;
{dict_of, _, _} ->
<<<<"json_codecs.json_encode_gleam__dict("/utf8, Var/binary>>/binary,
")"/utf8>>;
{tuple_of, _} ->
<<<<"json_codecs.json_encode_gleam__tuple("/utf8, Var/binary>>/binary,
")"/utf8>>;
{type_var, _} ->
<<"panic as \"cannot encode type variable\""/utf8>>
end.
-file("src/rally/generator/json_rpc_dispatch.gleam", 172).
-spec json_response_encode(libero@scanner:handler_endpoint()) -> binary().
json_response_encode(E) ->
Ok_encoder = json_encoder_for_fieldtype(erlang:element(4, E), <<"x"/utf8>>),
Err_encoder = json_encoder_for_fieldtype(erlang:element(5, E), <<"x"/utf8>>),
Ok_param = closure_param_for_fieldtype(erlang:element(4, E)),
Err_param = closure_param_for_fieldtype(erlang:element(5, E)),
<<<<<<<<<<<<<<<<"let encoded = json_codecs.json_encode_gleam_result__result(result, fn("/utf8,
Ok_param/binary>>/binary,
") { "/utf8>>/binary,
Ok_encoder/binary>>/binary,
" }, fn("/utf8>>/binary,
Err_param/binary>>/binary,
") { "/utf8>>/binary,
Err_encoder/binary>>/binary,
" })"/utf8>>.
-file("src/rally/generator/json_rpc_dispatch.gleam", 139).
-spec json_handler_call(libero@scanner:handler_endpoint(), binary(), boolean()) -> binary().
json_handler_call(E, Alias, Has_auth) ->
Extra = case Has_auth of
true ->
<<", identity:"/utf8>>;
false ->
<<""/utf8>>
end,
case erlang:element(8, E) of
{some, _} ->
<<<<<<<<<<<<Alias/binary, "."/utf8>>/binary, "server_"/utf8>>/binary,
(erlang:element(3, E))/binary>>/binary,
"(msg: msg, server_context: server_context"/utf8>>/binary,
Extra/binary>>/binary,
")"/utf8>>;
_ ->
Labeled = gleam@list:map(
erlang:element(6, E),
fun(P) ->
<<<<(erlang:element(1, P))/binary, ": "/utf8>>/binary,
(erlang:element(1, P))/binary>>
end
),
Args = lists:append(
Labeled,
[<<"server_context: server_context"/utf8, Extra/binary>>]
),
<<<<<<<<<<<<Alias/binary, "."/utf8>>/binary, "server_"/utf8>>/binary,
(erlang:element(3, E))/binary>>/binary,
"("/utf8>>/binary,
(gleam@string:join(Args, <<", "/utf8>>))/binary>>/binary,
")"/utf8>>
end.
-file("src/rally/generator/json_rpc_dispatch.gleam", 93).
-spec json_dispatch_arm(libero@scanner:handler_endpoint(), boolean(), binary()) -> binary().
json_dispatch_arm(E, Has_auth, Encode_prefix) ->
Alias = handler_alias(erlang:element(2, E)),
{Type_module, Type_name} = case erlang:element(8, E) of
{some, {Mod, Name}} ->
{Mod, Name};
_ ->
{erlang:element(2, E),
to_pascal_case(
<<"server_"/utf8, (erlang:element(3, E))/binary>>
)}
end,
Type_str = <<<<Type_module/binary, "."/utf8>>/binary, Type_name/binary>>,
Msg_decoder = <<"json_codecs.json_decode_"/utf8,
(libero@walker:qualified_atom_name(Type_module, Type_name))/binary>>,
Handler_call = json_handler_call(E, Alias, Has_auth),
{Ok_destructure, Ok_ctx} = case erlang:element(7, E) of
true ->
{<<"#(result, new_ctx)"/utf8>>, <<"new_ctx"/utf8>>};
false ->
{<<"result"/utf8>>, <<"server_context"/utf8>>}
end,
Response_encode = json_response_encode(E),
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" Ok(\""/utf8, Type_str/binary>>/binary,
"\") -> {
case "/utf8>>/binary,
Msg_decoder/binary>>/binary,
"(message) {
Error(errors) -> {
let error_frame = "/utf8>>/binary,
Encode_prefix/binary>>/binary,
"encode_error(Some(request_id), errors)
#(error_frame, server_context)
}
Ok(msg) -> {
case trace.try_call(fn() { "/utf8>>/binary,
Handler_call/binary>>/binary,
" }) {
Ok("/utf8>>/binary,
Ok_destructure/binary>>/binary,
") -> {
"/utf8>>/binary,
Response_encode/binary>>/binary,
"
let frame = "/utf8>>/binary,
Encode_prefix/binary>>/binary,
"encode_response(request_id, encoded)
#(frame, "/utf8>>/binary,
Ok_ctx/binary>>/binary,
")
}
Error(reason) -> {
let trace_id = trace.new_trace_id()
io.println_error(\"[libero] \" <> trace_id <> \" "/utf8>>/binary,
(erlang:element(3, E))/binary>>/binary,
": \" <> reason)
let error_frame = "/utf8>>/binary,
Encode_prefix/binary>>/binary,
"encode_error(Some(request_id), [JsonError(\"handler\", \"Something went wrong\")])
#(error_frame, server_context)
}
}
}
}
}"/utf8>>.
-file("src/rally/generator/json_rpc_dispatch.gleam", 48).
-spec generate_json_dispatch_function_with_prefix(
list(libero@scanner:handler_endpoint()),
boolean(),
binary()
) -> binary().
generate_json_dispatch_function_with_prefix(Endpoints, Has_auth, Encode_prefix) ->
case Endpoints of
[] ->
<<<<<<<<"\nfn json_dispatch(
message _message: Dynamic,
request_id request_id: Int,
server_context server_context: ServerContext,"/utf8,
(case Has_auth of
true ->
<<"\n identity _identity: auth.Identity,"/utf8>>;
false ->
<<""/utf8>>
end)/binary>>/binary,
"
) -> #(String, ServerContext) {
let error_frame = "/utf8>>/binary,
Encode_prefix/binary>>/binary,
"encode_error(Some(request_id), [JsonError(\"rpc\", \"no endpoints configured\")])
#(error_frame, server_context)
}\n"/utf8>>;
_ ->
Arms = begin
_pipe = gleam@list:map(
Endpoints,
fun(E) -> json_dispatch_arm(E, Has_auth, Encode_prefix) end
),
gleam@string:join(_pipe, <<"\n"/utf8>>)
end,
Catch_all = <<<<" Ok(other) -> {
let error_frame = "/utf8,
Encode_prefix/binary>>/binary,
"encode_error(Some(request_id), [JsonError(\"type\", \"unknown: \" <> other)])
#(error_frame, server_context)
}"/utf8>>,
<<<<<<<<<<<<<<<<"\nfn json_dispatch(
message message: Dynamic,
request_id request_id: Int,
server_context server_context: ServerContext,"/utf8,
(case Has_auth of
true ->
<<"\n identity identity: auth.Identity,"/utf8>>;
false ->
<<""/utf8>>
end)/binary>>/binary,
"
) -> #(String, ServerContext) {
case decode.run(message, decode.field(\"type\", decode.string, fn(x) { decode.success(x) })) {
Error(_) -> {
let error_frame = "/utf8>>/binary,
Encode_prefix/binary>>/binary,
"encode_error(Some(request_id), [JsonError(\"type\", \"missing or not a string\")])
#(error_frame, server_context)
}\n"/utf8>>/binary,
Arms/binary>>/binary,
"\n"/utf8>>/binary,
Catch_all/binary>>/binary,
"\n }\n}\n"/utf8>>
end.
-file("src/rally/generator/json_rpc_dispatch.gleam", 41).
-spec generate_json_dispatch_function(
list(libero@scanner:handler_endpoint()),
boolean()
) -> binary().
generate_json_dispatch_function(Endpoints, Has_auth) ->
generate_json_dispatch_function_with_prefix(
Endpoints,
Has_auth,
<<"wire."/utf8>>
).
-file("src/rally/generator/json_rpc_dispatch.gleam", 235).
-spec handler_imports(list(libero@scanner:handler_endpoint())) -> list(binary()).
handler_imports(Endpoints) ->
_pipe = Endpoints,
_pipe@1 = gleam@list:map(_pipe, fun(E) -> erlang:element(2, E) end),
_pipe@2 = gleam@list:unique(_pipe@1),
gleam@list:map(
_pipe@2,
fun(Mod) ->
Alias = handler_alias(Mod),
case begin
_pipe@3 = gleam@string:split(Mod, <<"/"/utf8>>),
gleam@list:last(_pipe@3)
end of
{ok, Seg} when Seg =:= Alias ->
<<"import "/utf8, Mod/binary>>;
_ ->
<<<<<<"import "/utf8, Mod/binary>>/binary, " as "/utf8>>/binary,
Alias/binary>>
end
end
).