Packages
oaspec
0.11.0
0.68.0
0.67.0
0.66.0
0.65.0
0.64.0
0.63.0
0.62.0
0.61.0
0.60.0
0.59.0
0.58.1
0.58.0
0.57.0
0.56.0
0.55.0
0.54.0
0.53.0
0.52.0
0.51.0
0.50.0
0.49.0
0.48.0
0.47.0
0.46.0
0.45.0
0.44.0
0.43.0
0.42.0
0.41.0
0.40.0
0.39.0
0.38.0
0.37.0
0.36.0
0.35.0
0.34.0
0.33.0
0.32.0
0.31.0
0.30.0
0.29.0
0.28.0
0.27.0
0.26.0
0.25.0
0.24.0
0.23.0
0.22.0
0.21.0
0.20.0
0.19.0
0.18.0
0.17.0
0.16.0
0.15.0
0.14.0
0.13.0
0.12.0
0.11.0
0.10.0
0.9.0
0.8.0
0.7.0
0.6.3
0.6.1
0.6.0
0.5.0
0.4.0
0.3.0
0.1.3
Generate Gleam code from OpenAPI 3.x specifications
Current section
Files
Jump to
Current section
Files
src/oaspec@codegen@server.erl
-module(oaspec@codegen@server).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/oaspec/codegen/server.gleam").
-export([generate/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.
-file("src/oaspec/codegen/server.gleam", 65).
?DOC(" Generate a single handler stub.\n").
-spec generate_handler(
gleam@string_tree:string_tree(),
binary(),
oaspec@openapi@spec:operation(oaspec@openapi@spec:resolved()),
oaspec@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_handler(Sb, Op_id, Operation, _) ->
Fn_name = oaspec@util@naming:operation_to_function_name(Op_id),
Request_type = <<(oaspec@util@naming:schema_to_type_name(Op_id))/binary,
"Request"/utf8>>,
Response_type = <<(oaspec@util@naming:schema_to_type_name(Op_id))/binary,
"Response"/utf8>>,
Sb@1 = case erlang:element(3, Operation) of
{some, Summary} ->
_pipe = Sb,
oaspec@util@string_extra:doc_comment(_pipe, Summary);
_ ->
Sb
end,
Sb@2 = case erlang:element(4, Operation) of
{some, Desc} ->
_pipe@1 = Sb@1,
oaspec@util@string_extra:doc_comment(_pipe@1, Desc);
_ ->
Sb@1
end,
Has_params = not gleam@list:is_empty(erlang:element(6, Operation)) orelse gleam@option:is_some(
erlang:element(7, Operation)
),
Sb@3 = case Has_params of
true ->
_pipe@2 = Sb@2,
oaspec@util@string_extra:line(
_pipe@2,
<<<<<<<<<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(req: request_types."/utf8>>/binary,
Request_type/binary>>/binary,
") -> response_types."/utf8>>/binary,
Response_type/binary>>/binary,
" {"/utf8>>
);
false ->
_pipe@3 = Sb@2,
oaspec@util@string_extra:line(
_pipe@3,
<<<<<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"() -> response_types."/utf8>>/binary,
Response_type/binary>>/binary,
" {"/utf8>>
)
end,
Sb@4 = case Has_params of
true ->
_pipe@4 = Sb@3,
oaspec@util@string_extra:indent(_pipe@4, 1, <<"let _ = req"/utf8>>);
false ->
Sb@3
end,
_pipe@5 = Sb@4,
_pipe@6 = oaspec@util@string_extra:indent(
_pipe@5,
1,
<<<<"panic as \"unimplemented: "/utf8, Fn_name/binary>>/binary,
"\""/utf8>>
),
_pipe@7 = oaspec@util@string_extra:line(_pipe@6, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@7).
-file("src/oaspec/codegen/server.gleam", 150).
?DOC(" Extract a short suffix from a URL expression for function naming.\n").
-spec url_expression_to_suffix(binary()) -> binary().
url_expression_to_suffix(Url_expression) ->
Parts = gleam@string:split(Url_expression, <<"/"/utf8>>),
case gleam@list:last(Parts) of
{ok, Last} ->
_pipe = Last,
_pipe@1 = gleam@string:replace(_pipe, <<"{"/utf8>>, <<""/utf8>>),
_pipe@2 = gleam@string:replace(_pipe@1, <<"}"/utf8>>, <<""/utf8>>),
_pipe@3 = gleam@string:replace(_pipe@2, <<"$"/utf8>>, <<""/utf8>>),
gleam@string:replace(_pipe@3, <<"#"/utf8>>, <<""/utf8>>);
{error, _} ->
<<"handler"/utf8>>
end.
-file("src/oaspec/codegen/server.gleam", 119).
?DOC(" Generate callback handler stubs for an operation's callbacks.\n").
-spec generate_callback_handlers(
gleam@string_tree:string_tree(),
binary(),
oaspec@openapi@spec:operation(oaspec@openapi@spec:resolved())
) -> gleam@string_tree:string_tree().
generate_callback_handlers(Sb, Op_id, Operation) ->
Callbacks = oaspec@codegen@ir_build:sorted_entries(
erlang:element(11, Operation)
),
gleam@list:fold(
Callbacks,
Sb,
fun(Sb@1, Entry) ->
{Callback_name, Callback} = Entry,
Callback_entries = oaspec@codegen@ir_build:sorted_entries(
erlang:element(2, Callback)
),
gleam@list:fold(
Callback_entries,
Sb@1,
fun(Sb@2, Cb_entry) ->
{Url_expression, _} = Cb_entry,
Fn_name = <<<<<<<<(oaspec@util@naming:operation_to_function_name(
Op_id
))/binary,
"_callback_"/utf8>>/binary,
(oaspec@util@naming:to_snake_case(Callback_name))/binary>>/binary,
"_"/utf8>>/binary,
(oaspec@util@naming:to_snake_case(
url_expression_to_suffix(Url_expression)
))/binary>>,
_pipe = Sb@2,
_pipe@1 = oaspec@util@string_extra:doc_comment(
_pipe,
<<<<<<"Callback handler stub for "/utf8,
Callback_name/binary>>/binary,
" on "/utf8>>/binary,
Op_id/binary>>
),
_pipe@2 = oaspec@util@string_extra:doc_comment(
_pipe@1,
<<"URL: "/utf8, Url_expression/binary>>
),
_pipe@3 = oaspec@util@string_extra:line(
_pipe@2,
<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"() -> String {"/utf8>>
),
_pipe@4 = oaspec@util@string_extra:indent(
_pipe@3,
1,
<<<<"panic as \"unimplemented: "/utf8, Fn_name/binary>>/binary,
"\""/utf8>>
),
_pipe@5 = oaspec@util@string_extra:line(
_pipe@4,
<<"}"/utf8>>
),
oaspec@util@string_extra:blank_line(_pipe@5)
end
)
end
).
-file("src/oaspec/codegen/server.gleam", 37).
?DOC(" Generate handler stubs for all operations.\n").
-spec generate_handlers(
oaspec@codegen@context:context(),
list({binary(),
oaspec@openapi@spec:operation(oaspec@openapi@spec:resolved()),
binary(),
oaspec@openapi@spec:http_method()})
) -> binary().
generate_handlers(Ctx, Operations) ->
Sb = begin
_pipe = oaspec@util@string_extra:file_header(<<"0.11.0"/utf8>>),
oaspec@util@string_extra:imports(
_pipe,
[<<(erlang:element(5, erlang:element(3, Ctx)))/binary,
"/request_types"/utf8>>,
<<(erlang:element(5, erlang:element(3, Ctx)))/binary,
"/response_types"/utf8>>]
)
end,
Sb@2 = gleam@list:fold(
Operations,
Sb,
fun(Sb@1, Op) ->
{Op_id, Operation, _, _} = Op,
generate_handler(Sb@1, Op_id, Operation, Ctx)
end
),
Sb@4 = gleam@list:fold(
Operations,
Sb@2,
fun(Sb@3, Op@1) ->
{Op_id@1, Operation@1, _, _} = Op@1,
generate_callback_handlers(Sb@3, Op_id@1, Operation@1)
end
),
oaspec@util@string_extra:to_string(Sb@4).
-file("src/oaspec/codegen/server.gleam", 845).
-spec route_arg_name(binary(), boolean()) -> binary().
route_arg_name(Name, Used) ->
case Used of
true ->
Name;
false ->
<<"_"/utf8, Name/binary>>
end.
-file("src/oaspec/codegen/server.gleam", 852).
-spec generate_cookie_lookup(gleam@string_tree:string_tree()) -> gleam@string_tree:string_tree().
generate_cookie_lookup(Sb) ->
_pipe = Sb,
_pipe@1 = oaspec@util@string_extra:doc_comment(
_pipe,
<<"Extract a cookie value from the Cookie header."/utf8>>
),
_pipe@2 = oaspec@util@string_extra:line(
_pipe@1,
<<"fn cookie_lookup(headers: Dict(String, String), key: String) -> Result(String, Nil) {"/utf8>>
),
_pipe@3 = oaspec@util@string_extra:indent(
_pipe@2,
1,
<<"case dict.get(headers, \"cookie\") {"/utf8>>
),
_pipe@4 = oaspec@util@string_extra:indent(_pipe@3, 2, <<"Ok(raw) ->"/utf8>>),
_pipe@5 = oaspec@util@string_extra:indent(
_pipe@4,
3,
<<"list.find_map(string.split(raw, \";\"), fn(part) {"/utf8>>
),
_pipe@6 = oaspec@util@string_extra:indent(
_pipe@5,
4,
<<"let trimmed = string.trim(part)"/utf8>>
),
_pipe@7 = oaspec@util@string_extra:indent(
_pipe@6,
4,
<<"case string.split_once(trimmed, on: \"=\") {"/utf8>>
),
_pipe@8 = oaspec@util@string_extra:indent(
_pipe@7,
5,
<<"Ok(#(cookie_key, cookie_value)) ->"/utf8>>
),
_pipe@9 = oaspec@util@string_extra:indent(
_pipe@8,
6,
<<"case string.trim(cookie_key) == key {"/utf8>>
),
_pipe@10 = oaspec@util@string_extra:indent(
_pipe@9,
7,
<<"True -> uri.percent_decode(string.trim(cookie_value))"/utf8>>
),
_pipe@11 = oaspec@util@string_extra:indent(
_pipe@10,
7,
<<"False -> Error(Nil)"/utf8>>
),
_pipe@12 = oaspec@util@string_extra:indent(_pipe@11, 6, <<"}"/utf8>>),
_pipe@13 = oaspec@util@string_extra:indent(
_pipe@12,
5,
<<"Error(_) -> Error(Nil)"/utf8>>
),
_pipe@14 = oaspec@util@string_extra:indent(_pipe@13, 4, <<"}"/utf8>>),
_pipe@15 = oaspec@util@string_extra:indent(_pipe@14, 3, <<"})"/utf8>>),
_pipe@16 = oaspec@util@string_extra:indent(
_pipe@15,
2,
<<"Error(_) -> Error(Nil)"/utf8>>
),
_pipe@17 = oaspec@util@string_extra:indent(_pipe@16, 1, <<"}"/utf8>>),
_pipe@18 = oaspec@util@string_extra:line(_pipe@17, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@18).
-file("src/oaspec/codegen/server.gleam", 917).
?DOC(" Generate code to construct a typed request from raw inputs.\n").
-spec generate_request_construction(
gleam@string_tree:string_tree(),
binary(),
binary(),
oaspec@openapi@spec:operation(oaspec@openapi@spec:resolved()),
binary(),
oaspec@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_request_construction(Sb, Request_type_name, Op_id, Operation, _, Ctx) ->
Sb@1 = case erlang:element(7, Operation) of
{some, {value, Rb}} ->
case oaspec@codegen@server_request_decode:request_body_uses_form_urlencoded(
Rb
) of
true ->
_pipe = Sb,
oaspec@util@string_extra:indent(
_pipe,
3,
<<"let form_body = parse_form_body(body)"/utf8>>
);
false ->
case oaspec@codegen@server_request_decode:request_body_uses_multipart(
Rb
) of
true ->
_pipe@1 = Sb,
oaspec@util@string_extra:indent(
_pipe@1,
3,
<<"let multipart_body = parse_multipart_body(body, headers)"/utf8>>
);
false ->
Sb
end
end;
_ ->
Sb
end,
Sb@2 = begin
_pipe@2 = Sb@1,
oaspec@util@string_extra:indent(
_pipe@2,
3,
<<<<"let request = request_types."/utf8, Request_type_name/binary>>/binary,
"("/utf8>>
)
end,
Sb@4 = gleam@list:index_fold(
gleam@list:filter_map(erlang:element(6, Operation), fun(R) -> case R of
{value, P} ->
{ok, P};
_ ->
{error, nil}
end end),
Sb@2,
fun(Sb@3, Param, _) ->
Field_name = oaspec@util@naming:to_snake_case(
erlang:element(2, Param)
),
Trailing = <<","/utf8>>,
Value_expr = case erlang:element(3, Param) of
in_path ->
Var_name = oaspec@util@naming:to_snake_case(
erlang:element(2, Param)
),
oaspec@codegen@server_request_decode:param_parse_expr(
Var_name,
Param
);
in_query ->
Key = erlang:element(2, Param),
case {oaspec@codegen@server_request_decode:is_deep_object_param(
Param,
Ctx
),
erlang:element(5, Param)} of
{true, true} ->
oaspec@codegen@server_request_decode:deep_object_required_expr(
Key,
Param,
Op_id,
Ctx
);
{true, false} ->
oaspec@codegen@server_request_decode:deep_object_optional_expr(
Key,
Param,
Op_id,
Ctx
);
{false, true} ->
oaspec@codegen@server_request_decode:query_required_expr(
Key,
Param
);
{false, false} ->
oaspec@codegen@server_request_decode:query_optional_expr(
Key,
Param
)
end;
in_header ->
Key@1 = string:lowercase(erlang:element(2, Param)),
case erlang:element(5, Param) of
true ->
oaspec@codegen@server_request_decode:header_required_expr(
Key@1,
Param
);
false ->
oaspec@codegen@server_request_decode:header_optional_expr(
Key@1,
Param
)
end;
in_cookie ->
Key@2 = erlang:element(2, Param),
case erlang:element(5, Param) of
true ->
oaspec@codegen@server_request_decode:cookie_required_expr(
Key@2,
Param
);
false ->
oaspec@codegen@server_request_decode:cookie_optional_expr(
Key@2,
Param
)
end
end,
_pipe@3 = Sb@3,
oaspec@util@string_extra:indent(
_pipe@3,
4,
<<<<<<Field_name/binary, ": "/utf8>>/binary, Value_expr/binary>>/binary,
Trailing/binary>>
)
end
),
Sb@5 = case erlang:element(7, Operation) of
{some, {value, Rb@1}} ->
Body_expr = oaspec@codegen@server_request_decode:generate_body_decode_expr(
Rb@1,
Op_id,
Ctx
),
_pipe@4 = Sb@4,
oaspec@util@string_extra:indent(
_pipe@4,
4,
<<<<"body: "/utf8, Body_expr/binary>>/binary, ","/utf8>>
);
_ ->
Sb@4
end,
_pipe@5 = Sb@5,
oaspec@util@string_extra:indent(_pipe@5, 3, <<")"/utf8>>).
-file("src/oaspec/codegen/server.gleam", 1168).
?DOC(" Get the encode function name for a schema reference.\n").
-spec get_encode_function(
gleam@option:option(oaspec@openapi@schema:schema_ref()),
oaspec@codegen@context:context()
) -> binary().
get_encode_function(Schema_ref, _) ->
case Schema_ref of
{some, {reference, _, Name}} ->
<<<<"encode.encode_"/utf8,
(oaspec@util@naming:to_snake_case(Name))/binary>>/binary,
"_json"/utf8>>;
{some, {inline, {array_schema, _, Items, _, _, _}}} ->
case Items of
{reference, _, Name@1} ->
<<<<"fn(items) { json.array(items, encode.encode_"/utf8,
(oaspec@util@naming:to_snake_case(Name@1))/binary>>/binary,
"_json) }"/utf8>>;
_ ->
<<"json.string"/utf8>>
end;
{some, {inline, {string_schema, _, _, _, _, _, _}}} ->
<<"json.string"/utf8>>;
{some, {inline, {integer_schema, _, _, _, _, _, _, _}}} ->
<<"json.int"/utf8>>;
{some, {inline, {number_schema, _, _, _, _, _, _, _}}} ->
<<"json.float"/utf8>>;
{some, {inline, {boolean_schema, _}}} ->
<<"json.bool"/utf8>>;
_ ->
<<"json.string"/utf8>>
end.
-file("src/oaspec/codegen/server.gleam", 1016).
?DOC(" Generate code to convert a handler response to ServerResponse.\n").
-spec generate_response_conversion(
gleam@string_tree:string_tree(),
binary(),
oaspec@openapi@spec:operation(oaspec@openapi@spec:resolved()),
oaspec@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_response_conversion(Sb, Response_type_name, Operation, Ctx) ->
Responses = oaspec@util@http:sort_response_entries(
maps:to_list(erlang:element(8, Operation))
),
case gleam@list:is_empty(Responses) of
true ->
_pipe = Sb,
oaspec@util@string_extra:indent(
_pipe,
3,
<<"ServerResponse(status: 200, body: \"\", headers: [])"/utf8>>
);
false ->
Sb@1 = begin
_pipe@1 = Sb,
oaspec@util@string_extra:indent(
_pipe@1,
3,
<<"case response {"/utf8>>
)
end,
Sb@3 = gleam@list:fold(
Responses,
Sb@1,
fun(Sb@2, Entry) ->
{Status_code, Ref_or} = Entry,
case Ref_or of
{value, Response} ->
Variant_name = <<Response_type_name/binary,
(oaspec@util@http:status_code_suffix(
Status_code
))/binary>>,
Status_int = oaspec@util@http:status_code_to_int(
Status_code
),
Content_entries = maps:to_list(
erlang:element(3, Response)
),
case Content_entries of
[] ->
_pipe@2 = Sb@2,
oaspec@util@string_extra:indent(
_pipe@2,
4,
<<<<<<<<"response_types."/utf8,
Variant_name/binary>>/binary,
" -> ServerResponse(status: "/utf8>>/binary,
Status_int/binary>>/binary,
", body: \"\", headers: [])"/utf8>>
);
[{Media_type_name, Media_type}] ->
case Media_type_name of
<<"application/json"/utf8>> ->
case erlang:element(2, Media_type) of
{some, _} ->
Encode_fn = get_encode_function(
erlang:element(
2,
Media_type
),
Ctx
),
_pipe@3 = Sb@2,
oaspec@util@string_extra:indent(
_pipe@3,
4,
<<<<<<<<<<<<"response_types."/utf8,
Variant_name/binary>>/binary,
"(data) -> ServerResponse(status: "/utf8>>/binary,
Status_int/binary>>/binary,
", body: json.to_string("/utf8>>/binary,
Encode_fn/binary>>/binary,
"(data)), headers: [#(\"content-type\", \"application/json\")])"/utf8>>
);
none ->
_pipe@4 = Sb@2,
oaspec@util@string_extra:indent(
_pipe@4,
4,
<<<<<<<<"response_types."/utf8,
Variant_name/binary>>/binary,
" -> ServerResponse(status: "/utf8>>/binary,
Status_int/binary>>/binary,
", body: \"\", headers: [])"/utf8>>
)
end;
<<"text/plain"/utf8>> ->
case erlang:element(2, Media_type) of
{some, _} ->
_pipe@5 = Sb@2,
oaspec@util@string_extra:indent(
_pipe@5,
4,
<<<<<<<<<<<<"response_types."/utf8,
Variant_name/binary>>/binary,
"(data) -> ServerResponse(status: "/utf8>>/binary,
Status_int/binary>>/binary,
", body: data, headers: [#(\"content-type\", \""/utf8>>/binary,
Media_type_name/binary>>/binary,
"\")])"/utf8>>
);
none ->
_pipe@6 = Sb@2,
oaspec@util@string_extra:indent(
_pipe@6,
4,
<<<<<<<<"response_types."/utf8,
Variant_name/binary>>/binary,
" -> ServerResponse(status: "/utf8>>/binary,
Status_int/binary>>/binary,
", body: \"\", headers: [])"/utf8>>
)
end;
<<"application/xml"/utf8>> ->
case erlang:element(2, Media_type) of
{some, _} ->
_pipe@5 = Sb@2,
oaspec@util@string_extra:indent(
_pipe@5,
4,
<<<<<<<<<<<<"response_types."/utf8,
Variant_name/binary>>/binary,
"(data) -> ServerResponse(status: "/utf8>>/binary,
Status_int/binary>>/binary,
", body: data, headers: [#(\"content-type\", \""/utf8>>/binary,
Media_type_name/binary>>/binary,
"\")])"/utf8>>
);
none ->
_pipe@6 = Sb@2,
oaspec@util@string_extra:indent(
_pipe@6,
4,
<<<<<<<<"response_types."/utf8,
Variant_name/binary>>/binary,
" -> ServerResponse(status: "/utf8>>/binary,
Status_int/binary>>/binary,
", body: \"\", headers: [])"/utf8>>
)
end;
<<"text/xml"/utf8>> ->
case erlang:element(2, Media_type) of
{some, _} ->
_pipe@5 = Sb@2,
oaspec@util@string_extra:indent(
_pipe@5,
4,
<<<<<<<<<<<<"response_types."/utf8,
Variant_name/binary>>/binary,
"(data) -> ServerResponse(status: "/utf8>>/binary,
Status_int/binary>>/binary,
", body: data, headers: [#(\"content-type\", \""/utf8>>/binary,
Media_type_name/binary>>/binary,
"\")])"/utf8>>
);
none ->
_pipe@6 = Sb@2,
oaspec@util@string_extra:indent(
_pipe@6,
4,
<<<<<<<<"response_types."/utf8,
Variant_name/binary>>/binary,
" -> ServerResponse(status: "/utf8>>/binary,
Status_int/binary>>/binary,
", body: \"\", headers: [])"/utf8>>
)
end;
<<"application/octet-stream"/utf8>> ->
case erlang:element(2, Media_type) of
{some, _} ->
_pipe@5 = Sb@2,
oaspec@util@string_extra:indent(
_pipe@5,
4,
<<<<<<<<<<<<"response_types."/utf8,
Variant_name/binary>>/binary,
"(data) -> ServerResponse(status: "/utf8>>/binary,
Status_int/binary>>/binary,
", body: data, headers: [#(\"content-type\", \""/utf8>>/binary,
Media_type_name/binary>>/binary,
"\")])"/utf8>>
);
none ->
_pipe@6 = Sb@2,
oaspec@util@string_extra:indent(
_pipe@6,
4,
<<<<<<<<"response_types."/utf8,
Variant_name/binary>>/binary,
" -> ServerResponse(status: "/utf8>>/binary,
Status_int/binary>>/binary,
", body: \"\", headers: [])"/utf8>>
)
end;
_ ->
case erlang:element(2, Media_type) of
{some, _} ->
Encode_fn@1 = get_encode_function(
erlang:element(
2,
Media_type
),
Ctx
),
_pipe@7 = Sb@2,
oaspec@util@string_extra:indent(
_pipe@7,
4,
<<<<<<<<<<<<<<<<"response_types."/utf8,
Variant_name/binary>>/binary,
"(data) -> ServerResponse(status: "/utf8>>/binary,
Status_int/binary>>/binary,
", body: json.to_string("/utf8>>/binary,
Encode_fn@1/binary>>/binary,
"(data)), headers: [#(\"content-type\", \""/utf8>>/binary,
Media_type_name/binary>>/binary,
"\")])"/utf8>>
);
none ->
_pipe@8 = Sb@2,
oaspec@util@string_extra:indent(
_pipe@8,
4,
<<<<<<<<"response_types."/utf8,
Variant_name/binary>>/binary,
" -> ServerResponse(status: "/utf8>>/binary,
Status_int/binary>>/binary,
", body: \"\", headers: [])"/utf8>>
)
end
end;
[{First_media_type, _}, _ | _] ->
_pipe@9 = Sb@2,
oaspec@util@string_extra:indent(
_pipe@9,
4,
<<<<<<<<<<<<"response_types."/utf8,
Variant_name/binary>>/binary,
"(data) -> ServerResponse(status: "/utf8>>/binary,
Status_int/binary>>/binary,
", body: data, headers: [#(\"content-type\", \""/utf8>>/binary,
First_media_type/binary>>/binary,
"\")])"/utf8>>
)
end;
_ ->
Sb@2
end
end
),
_pipe@10 = Sb@3,
oaspec@util@string_extra:indent(_pipe@10, 3, <<"}"/utf8>>)
end.
-file("src/oaspec/codegen/server.gleam", 878).
?DOC(" Generate the body of a single route case branch.\n").
-spec generate_route_body(
gleam@string_tree:string_tree(),
binary(),
binary(),
oaspec@openapi@spec:operation(oaspec@openapi@spec:resolved()),
binary(),
boolean(),
oaspec@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_route_body(Sb, Op_id, Fn_name, Operation, Path, Has_params, Ctx) ->
Type_name = oaspec@util@naming:schema_to_type_name(Op_id),
Response_type_name = <<Type_name/binary, "Response"/utf8>>,
case Has_params of
false ->
_pipe = Sb,
_pipe@1 = oaspec@util@string_extra:indent(
_pipe,
3,
<<<<"let response = handlers."/utf8, Fn_name/binary>>/binary,
"()"/utf8>>
),
generate_response_conversion(
_pipe@1,
Response_type_name,
Operation,
Ctx
);
true ->
Request_type_name = <<Type_name/binary, "Request"/utf8>>,
Sb@1 = generate_request_construction(
Sb,
Request_type_name,
Op_id,
Operation,
Path,
Ctx
),
_pipe@2 = Sb@1,
_pipe@3 = oaspec@util@string_extra:indent(
_pipe@2,
3,
<<<<"let response = handlers."/utf8, Fn_name/binary>>/binary,
"(request)"/utf8>>
),
generate_response_conversion(
_pipe@3,
Response_type_name,
Operation,
Ctx
)
end.
-file("src/oaspec/codegen/server.gleam", 1215).
?DOC(" Check if a path segment is a parameter.\n").
-spec is_path_param(binary()) -> boolean().
is_path_param(Segment) ->
case Segment of
<<"{"/utf8, _/binary>> ->
true;
_ ->
false
end.
-file("src/oaspec/codegen/server.gleam", 1223).
?DOC(" Extract parameter name from {name}.\n").
-spec extract_param_name(binary()) -> binary().
extract_param_name(Segment) ->
_pipe = Segment,
_pipe@1 = gleam@string:replace(_pipe, <<"{"/utf8>>, <<""/utf8>>),
gleam@string:replace(_pipe@1, <<"}"/utf8>>, <<""/utf8>>).
-file("src/oaspec/codegen/server.gleam", 1194).
?DOC(" Convert an OpenAPI path to a Gleam pattern match expression.\n").
-spec path_to_pattern(binary()) -> binary().
path_to_pattern(Path) ->
Segments = begin
_pipe = Path,
_pipe@1 = gleam@string:split(_pipe, <<"/"/utf8>>),
gleam@list:filter(_pipe@1, fun(S) -> S /= <<""/utf8>> end)
end,
Patterns = gleam@list:map(Segments, fun(Seg) -> case is_path_param(Seg) of
true ->
Param_name = extract_param_name(Seg),
oaspec@util@naming:to_snake_case(Param_name);
false ->
<<<<"\""/utf8, Seg/binary>>/binary, "\""/utf8>>
end end),
<<<<"["/utf8,
(oaspec@util@string_extra:join_with(Patterns, <<", "/utf8>>))/binary>>/binary,
"]"/utf8>>.
-file("src/oaspec/codegen/server.gleam", 165).
?DOC(" Generate a router module that dispatches requests.\n").
-spec generate_router(
oaspec@codegen@context:context(),
list({binary(),
oaspec@openapi@spec:operation(oaspec@openapi@spec:resolved()),
binary(),
oaspec@openapi@spec:http_method()})
) -> binary().
generate_router(Ctx, Operations) ->
Has_deep_object = gleam@list:any(
Operations,
fun(Op) ->
{_, Operation, _, _} = Op,
gleam@list:any(
erlang:element(6, Operation),
fun(Ref_p) -> case Ref_p of
{value, P} ->
oaspec@codegen@server_request_decode:is_deep_object_param(
P,
Ctx
);
_ ->
false
end end
)
end
),
Has_deep_object_with_ap = gleam@list:any(
Operations,
fun(Op@1) ->
{_, Operation@1, _, _} = Op@1,
gleam@list:any(
erlang:element(6, Operation@1),
fun(Ref_p@1) -> case Ref_p@1 of
{value, P@1} ->
oaspec@codegen@server_request_decode:is_deep_object_param(
P@1,
Ctx
)
andalso oaspec@codegen@server_request_decode:deep_object_has_additional_properties(
P@1,
Ctx
);
_ ->
false
end end
)
end
),
Needs_deep_object_present = gleam@list:any(
Operations,
fun(Op@2) ->
{_, Operation@2, _, _} = Op@2,
gleam@list:any(
erlang:element(6, Operation@2),
fun(Ref_p@2) -> case Ref_p@2 of
{value, P@2} ->
(oaspec@codegen@server_request_decode:is_deep_object_param(
P@2,
Ctx
)
andalso not erlang:element(5, P@2))
andalso not oaspec@codegen@server_request_decode:deep_object_has_untyped_additional_properties(
P@2,
Ctx
);
_ ->
false
end end
)
end
),
Has_deep_object_untyped_ap = gleam@list:any(
Operations,
fun(Op@3) ->
{_, Operation@3, _, _} = Op@3,
gleam@list:any(
erlang:element(6, Operation@3),
fun(Ref_p@3) -> case Ref_p@3 of
{value, P@3} ->
oaspec@codegen@server_request_decode:is_deep_object_param(
P@3,
Ctx
)
andalso oaspec@codegen@server_request_decode:deep_object_has_untyped_additional_properties(
P@3,
Ctx
);
_ ->
false
end end
)
end
),
Has_form_urlencoded_body = gleam@list:any(
Operations,
fun(Op@4) ->
{_, Operation@4, _, _} = Op@4,
oaspec@codegen@server_request_decode:operation_uses_form_urlencoded_body(
Operation@4
)
end
),
Has_multipart_body = gleam@list:any(
Operations,
fun(Op@5) ->
{_, Operation@5, _, _} = Op@5,
oaspec@codegen@server_request_decode:operation_uses_multipart_body(
Operation@5
)
end
),
Has_nested_form_urlencoded_body = gleam@list:any(
Operations,
fun(Op@6) ->
{_, Operation@6, _, _} = Op@6,
case erlang:element(7, Operation@6) of
{some, {value, Rb}} ->
oaspec@codegen@server_request_decode:form_urlencoded_body_has_nested_object(
Rb,
Ctx
);
_ ->
false
end
end
),
Needs_dict = gleam@list:any(
Operations,
fun(Op@7) ->
{_, Operation@7, _, _} = Op@7,
Has_query = gleam@list:any(
erlang:element(6, Operation@7),
fun(Ref_p@4) -> case Ref_p@4 of
{value, P@4} ->
erlang:element(3, P@4) =:= in_query;
_ ->
false
end end
),
Has_header = gleam@list:any(
erlang:element(6, Operation@7),
fun(Ref_p@5) -> case Ref_p@5 of
{value, P@5} ->
erlang:element(3, P@5) =:= in_header;
_ ->
false
end end
),
Has_query orelse Has_header
end
),
Needs_int = gleam@list:any(
Operations,
fun(Op@8) ->
{_, Operation@8, _, _} = Op@8,
(gleam@list:any(
erlang:element(6, Operation@8),
fun(Ref_p@6) -> case Ref_p@6 of
{value, P@6} ->
oaspec@codegen@server_request_decode:query_schema_needs_int(
oaspec@openapi@spec:parameter_schema(P@6)
)
orelse oaspec@codegen@server_request_decode:deep_object_param_needs_int(
P@6,
Ctx
);
_ ->
false
end end
)
orelse case erlang:element(7, Operation@8) of
{some, {value, Rb@1}} ->
oaspec@codegen@server_request_decode:form_urlencoded_body_needs_int(
Rb@1,
Ctx
);
_ ->
false
end)
orelse case erlang:element(7, Operation@8) of
{some, {value, Rb@2}} ->
oaspec@codegen@server_request_decode:multipart_body_needs_int(
Rb@2,
Ctx
);
_ ->
false
end
end
),
Needs_float = gleam@list:any(
Operations,
fun(Op@9) ->
{_, Operation@9, _, _} = Op@9,
(gleam@list:any(
erlang:element(6, Operation@9),
fun(Ref_p@7) -> case Ref_p@7 of
{value, P@7} ->
oaspec@codegen@server_request_decode:query_schema_needs_float(
oaspec@openapi@spec:parameter_schema(P@7)
)
orelse oaspec@codegen@server_request_decode:deep_object_param_needs_float(
P@7,
Ctx
);
_ ->
false
end end
)
orelse case erlang:element(7, Operation@9) of
{some, {value, Rb@3}} ->
oaspec@codegen@server_request_decode:form_urlencoded_body_needs_float(
Rb@3,
Ctx
);
_ ->
false
end)
orelse case erlang:element(7, Operation@9) of
{some, {value, Rb@4}} ->
oaspec@codegen@server_request_decode:multipart_body_needs_float(
Rb@4,
Ctx
);
_ ->
false
end
end
),
Needs_string = ((Has_form_urlencoded_body orelse Has_multipart_body) orelse Has_deep_object_with_ap)
orelse gleam@list:any(
Operations,
fun(Op@10) ->
{_, Operation@10, _, _} = Op@10,
gleam@list:any(
erlang:element(6, Operation@10),
fun(Ref_p@8) -> case Ref_p@8 of
{value, P@8} ->
case erlang:element(3, P@8) of
in_cookie ->
true;
in_query ->
oaspec@codegen@server_request_decode:query_schema_needs_string(
oaspec@openapi@spec:parameter_schema(
P@8
)
)
orelse oaspec@codegen@server_request_decode:deep_object_param_needs_string(
P@8,
Ctx
);
in_header ->
oaspec@codegen@server_request_decode:query_schema_needs_string(
oaspec@openapi@spec:parameter_schema(
P@8
)
)
orelse oaspec@codegen@server_request_decode:deep_object_param_needs_string(
P@8,
Ctx
);
in_path ->
oaspec@codegen@server_request_decode:query_schema_needs_string(
oaspec@openapi@spec:parameter_schema(
P@8
)
)
end;
_ ->
false
end end
)
orelse case erlang:element(7, Operation@10) of
{some, {value, Rb@5}} ->
oaspec@codegen@server_request_decode:form_urlencoded_body_needs_string(
Rb@5,
Ctx
);
_ ->
false
end
end
),
Needs_cookie_lookup = gleam@list:any(
Operations,
fun(Op@11) ->
{_, Operation@11, _, _} = Op@11,
gleam@list:any(
erlang:element(6, Operation@11),
fun(Ref_p@9) -> case Ref_p@9 of
{value, P@9} ->
erlang:element(3, P@9) =:= in_cookie;
_ ->
false
end end
)
end
),
Needs_list_import = (((Needs_cookie_lookup orelse Has_deep_object) orelse Has_form_urlencoded_body)
orelse Has_multipart_body)
orelse gleam@list:any(
Operations,
fun(Op@12) ->
{_, Operation@12, _, _} = Op@12,
gleam@list:any(
erlang:element(6, Operation@12),
fun(Ref_p@10) -> case Ref_p@10 of
{value, P@10} ->
case {erlang:element(3, P@10),
oaspec@openapi@spec:parameter_schema(P@10)} of
{in_query,
{some,
{inline, {array_schema, _, _, _, _, _}}}} ->
true;
{in_header,
{some,
{inline, {array_schema, _, _, _, _, _}}}} ->
true;
{_, _} ->
false
end;
_ ->
false
end end
)
end
),
Needs_uri_import = Needs_cookie_lookup orelse Has_form_urlencoded_body,
Needs_option = (oaspec@codegen@import_analysis:operations_have_optional_params(
Operations
)
orelse oaspec@codegen@import_analysis:operations_have_optional_body(
Operations
))
orelse gleam@list:any(
Operations,
fun(Op@13) ->
{_, Operation@13, _, _} = Op@13,
Has_optional_deep_object_fields = gleam@list:any(
erlang:element(6, Operation@13),
fun(Ref_p@11) -> case Ref_p@11 of
{value, P@11} ->
oaspec@codegen@server_request_decode:deep_object_param_has_optional_fields(
P@11,
Ctx
);
_ ->
false
end end
),
Has_optional_form_urlencoded_fields = case erlang:element(
7,
Operation@13
) of
{some, {value, Rb@6}} ->
oaspec@codegen@server_request_decode:form_urlencoded_body_has_optional_fields(
Rb@6,
Ctx
);
_ ->
false
end,
Has_optional_multipart_fields = case erlang:element(7, Operation@13) of
{some, {value, Rb@7}} ->
oaspec@codegen@server_request_decode:multipart_body_has_optional_fields(
Rb@7,
Ctx
);
_ ->
false
end,
(Has_optional_deep_object_fields orelse Has_optional_form_urlencoded_fields)
orelse Has_optional_multipart_fields
end
),
Needs_json = gleam@list:any(
Operations,
fun(Op@14) ->
{_, Operation@14, _, _} = Op@14,
Responses = maps:to_list(erlang:element(8, Operation@14)),
gleam@list:any(
Responses,
fun(Entry) ->
{_, Ref_or} = Entry,
case Ref_or of
{value, Response} ->
Content_entries = maps:to_list(
erlang:element(3, Response)
),
case Content_entries of
[{Media_type_name, Media_type}] ->
case Media_type_name of
<<"application/json"/utf8>> ->
case erlang:element(2, Media_type) of
{some, _} ->
true;
none ->
false
end;
_ ->
false
end;
_ ->
false
end;
_ ->
false
end
end
)
end
),
Needs_decode = gleam@list:any(
Operations,
fun(Op@15) ->
{_, Operation@15, _, _} = Op@15,
case erlang:element(7, Operation@15) of
{some, {value, Rb@8}} ->
gleam@list:any(
maps:to_list(erlang:element(3, Rb@8)),
fun(Entry@1) ->
{Content_type, _} = Entry@1,
Content_type =:= <<"application/json"/utf8>>
end
);
_ ->
false
end
end
),
Needs_encode = Needs_json,
Uses_query = gleam@list:any(
Operations,
fun(Op@16) ->
{_, Operation@16, _, _} = Op@16,
gleam@list:any(
erlang:element(6, Operation@16),
fun(Ref_p@12) -> case Ref_p@12 of
{value, P@12} ->
erlang:element(3, P@12) =:= in_query;
_ ->
false
end end
)
end
),
Uses_headers = Has_multipart_body orelse gleam@list:any(
Operations,
fun(Op@17) ->
{_, Operation@17, _, _} = Op@17,
gleam@list:any(
erlang:element(6, Operation@17),
fun(Ref_p@13) -> case Ref_p@13 of
{value, P@13} ->
(erlang:element(3, P@13) =:= in_header) orelse (erlang:element(
3,
P@13
)
=:= in_cookie);
_ ->
false
end end
)
end
),
Uses_body = gleam@list:any(
Operations,
fun(Op@18) ->
{_, Operation@18, _, _} = Op@18,
gleam@option:is_some(erlang:element(7, Operation@18))
end
),
Has_params_ops = gleam@list:any(
Operations,
fun(Op@19) ->
{_, Operation@19, _, _} = Op@19,
not gleam@list:is_empty(erlang:element(6, Operation@19)) orelse gleam@option:is_some(
erlang:element(7, Operation@19)
)
end
),
_ = Needs_dict,
Std_imports = [<<"gleam/dict.{type Dict}"/utf8>>],
Std_imports@1 = case Needs_list_import of
true ->
lists:append(Std_imports, [<<"gleam/list"/utf8>>]);
false ->
Std_imports
end,
Std_imports@2 = case Needs_uri_import of
true ->
lists:append(Std_imports@1, [<<"gleam/uri"/utf8>>]);
false ->
Std_imports@1
end,
Std_imports@3 = case Needs_int of
true ->
lists:append(Std_imports@2, [<<"gleam/int"/utf8>>]);
false ->
Std_imports@2
end,
Std_imports@4 = case Needs_float of
true ->
lists:append(Std_imports@3, [<<"gleam/float"/utf8>>]);
false ->
Std_imports@3
end,
Std_imports@5 = case Needs_option of
true ->
lists:append(Std_imports@4, [<<"gleam/option.{None, Some}"/utf8>>]);
false ->
Std_imports@4
end,
Std_imports@6 = case Needs_json of
true ->
lists:append(Std_imports@5, [<<"gleam/json"/utf8>>]);
false ->
Std_imports@5
end,
Std_imports@7 = case Needs_string of
true ->
lists:append(Std_imports@6, [<<"gleam/string"/utf8>>]);
false ->
Std_imports@6
end,
Std_imports@8 = case Has_deep_object_untyped_ap of
true ->
lists:append(Std_imports@7, [<<"gleam/dynamic"/utf8>>]);
false ->
Std_imports@7
end,
Pkg_imports = [<<(erlang:element(5, erlang:element(3, Ctx)))/binary,
"/handlers"/utf8>>],
Pkg_imports@1 = case (Has_deep_object orelse Has_form_urlencoded_body)
orelse Has_multipart_body of
true ->
lists:append(
Pkg_imports,
[<<(erlang:element(5, erlang:element(3, Ctx)))/binary,
"/types"/utf8>>]
);
false ->
Pkg_imports
end,
Pkg_imports@2 = case Needs_decode of
true ->
lists:append(
Pkg_imports@1,
[<<(erlang:element(5, erlang:element(3, Ctx)))/binary,
"/decode"/utf8>>]
);
false ->
Pkg_imports@1
end,
Pkg_imports@3 = case Needs_encode of
true ->
lists:append(
Pkg_imports@2,
[<<(erlang:element(5, erlang:element(3, Ctx)))/binary,
"/encode"/utf8>>]
);
false ->
Pkg_imports@2
end,
Pkg_imports@4 = case Has_params_ops of
true ->
lists:append(
Pkg_imports@3,
[<<(erlang:element(5, erlang:element(3, Ctx)))/binary,
"/request_types"/utf8>>,
<<(erlang:element(5, erlang:element(3, Ctx)))/binary,
"/response_types"/utf8>>]
);
false ->
lists:append(
Pkg_imports@3,
[<<(erlang:element(5, erlang:element(3, Ctx)))/binary,
"/response_types"/utf8>>]
)
end,
All_imports = lists:append(Std_imports@8, Pkg_imports@4),
Sb = begin
_pipe = oaspec@util@string_extra:file_header(<<"0.11.0"/utf8>>),
oaspec@util@string_extra:imports(_pipe, All_imports)
end,
Sb@1 = begin
_pipe@1 = Sb,
_pipe@2 = oaspec@util@string_extra:doc_comment(
_pipe@1,
<<"A server response with status code, body, and headers."/utf8>>
),
_pipe@3 = oaspec@util@string_extra:line(
_pipe@2,
<<"pub type ServerResponse {"/utf8>>
),
_pipe@4 = oaspec@util@string_extra:indent(
_pipe@3,
1,
<<"ServerResponse(status: Int, body: String, headers: List(#(String, String)))"/utf8>>
),
_pipe@5 = oaspec@util@string_extra:line(_pipe@4, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@5)
end,
Sb@2 = case Needs_deep_object_present of
true ->
_pipe@6 = Sb@1,
_pipe@7 = oaspec@util@string_extra:line(
_pipe@6,
<<"fn deep_object_present(query: Dict(String, List(String)), prefix: String, props: List(String)) -> Bool {"/utf8>>
),
_pipe@8 = oaspec@util@string_extra:indent(
_pipe@7,
1,
<<"list.any(props, fn(prop) { dict.has_key(query, prefix <> \"[\" <> prop <> \"]\") })"/utf8>>
),
_pipe@9 = oaspec@util@string_extra:line(_pipe@8, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@9);
false ->
Sb@1
end,
Sb@3 = case Has_deep_object_with_ap of
true ->
_pipe@10 = Sb@2,
_pipe@11 = oaspec@util@string_extra:line(
_pipe@10,
<<"fn deep_object_present_any(query: Dict(String, List(String)), prefix: String) -> Bool {"/utf8>>
),
_pipe@12 = oaspec@util@string_extra:indent(
_pipe@11,
1,
<<"let prefix_bracket = prefix <> \"[\""/utf8>>
),
_pipe@13 = oaspec@util@string_extra:indent(
_pipe@12,
1,
<<"dict.fold(query, False, fn(found, k, _v) { found || string.starts_with(k, prefix_bracket) })"/utf8>>
),
_pipe@14 = oaspec@util@string_extra:line(_pipe@13, <<"}"/utf8>>),
_pipe@15 = oaspec@util@string_extra:blank_line(_pipe@14),
_pipe@16 = oaspec@util@string_extra:line(
_pipe@15,
<<"fn deep_object_additional_properties(query: Dict(String, List(String)), prefix: String, known_props: List(String)) -> Dict(String, List(String)) {"/utf8>>
),
_pipe@17 = oaspec@util@string_extra:indent(
_pipe@16,
1,
<<"let prefix_bracket = prefix <> \"[\""/utf8>>
),
_pipe@18 = oaspec@util@string_extra:indent(
_pipe@17,
1,
<<"let prefix_len = string.length(prefix_bracket)"/utf8>>
),
_pipe@19 = oaspec@util@string_extra:indent(
_pipe@18,
1,
<<"dict.fold(query, dict.new(), fn(acc, k, v) {"/utf8>>
),
_pipe@20 = oaspec@util@string_extra:indent(
_pipe@19,
2,
<<"case string.starts_with(k, prefix_bracket) && string.ends_with(k, \"]\") {"/utf8>>
),
_pipe@21 = oaspec@util@string_extra:indent(
_pipe@20,
3,
<<"True -> {"/utf8>>
),
_pipe@22 = oaspec@util@string_extra:indent(
_pipe@21,
4,
<<"let prop = string.slice(k, prefix_len, string.length(k) - prefix_len - 1)"/utf8>>
),
_pipe@23 = oaspec@util@string_extra:indent(
_pipe@22,
4,
<<"case list.contains(known_props, prop) { True -> acc False -> dict.insert(acc, prop, v) }"/utf8>>
),
_pipe@24 = oaspec@util@string_extra:indent(
_pipe@23,
3,
<<"}"/utf8>>
),
_pipe@25 = oaspec@util@string_extra:indent(
_pipe@24,
3,
<<"False -> acc"/utf8>>
),
_pipe@26 = oaspec@util@string_extra:indent(
_pipe@25,
2,
<<"}"/utf8>>
),
_pipe@27 = oaspec@util@string_extra:indent(
_pipe@26,
1,
<<"})"/utf8>>
),
_pipe@28 = oaspec@util@string_extra:line(_pipe@27, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@28);
false ->
Sb@2
end,
Sb@4 = case Has_deep_object_untyped_ap of
true ->
_pipe@29 = Sb@3,
_pipe@30 = oaspec@util@string_extra:line(
_pipe@29,
<<"@external(erlang, \"gleam_stdlib\", \"identity\")"/utf8>>
),
_pipe@31 = oaspec@util@string_extra:line(
_pipe@30,
<<"fn coerce_dict(value: Dict(String, List(String))) -> Dict(String, dynamic.Dynamic)"/utf8>>
),
oaspec@util@string_extra:blank_line(_pipe@31);
false ->
Sb@3
end,
Sb@5 = case Has_form_urlencoded_body of
true ->
_pipe@32 = Sb@4,
_pipe@33 = oaspec@util@string_extra:line(
_pipe@32,
<<"fn form_url_decode(value: String) -> String {"/utf8>>
),
_pipe@34 = oaspec@util@string_extra:indent(
_pipe@33,
1,
<<"let value = string.replace(value, \"+\", \" \")"/utf8>>
),
_pipe@35 = oaspec@util@string_extra:indent(
_pipe@34,
1,
<<"case uri.percent_decode(value) { Ok(decoded) -> decoded Error(_) -> value }"/utf8>>
),
_pipe@36 = oaspec@util@string_extra:line(_pipe@35, <<"}"/utf8>>),
_pipe@37 = oaspec@util@string_extra:blank_line(_pipe@36),
_pipe@38 = oaspec@util@string_extra:line(
_pipe@37,
<<"fn parse_form_body(body: String) -> Dict(String, List(String)) {"/utf8>>
),
_pipe@39 = oaspec@util@string_extra:indent(
_pipe@38,
1,
<<"let parts = case body { \"\" -> [] _ -> string.split(body, \"&\") }"/utf8>>
),
_pipe@40 = oaspec@util@string_extra:indent(
_pipe@39,
1,
<<"list.fold(parts, dict.new(), fn(acc, part) {"/utf8>>
),
_pipe@41 = oaspec@util@string_extra:indent(
_pipe@40,
2,
<<"case part {"/utf8>>
),
_pipe@42 = oaspec@util@string_extra:indent(
_pipe@41,
3,
<<"\"\" -> acc"/utf8>>
),
_pipe@43 = oaspec@util@string_extra:indent(
_pipe@42,
3,
<<"_ ->"/utf8>>
),
_pipe@44 = oaspec@util@string_extra:indent(
_pipe@43,
4,
<<"case string.split_once(part, on: \"=\") {"/utf8>>
),
_pipe@45 = oaspec@util@string_extra:indent(
_pipe@44,
5,
<<"Ok(#(raw_key, raw_value)) -> {"/utf8>>
),
_pipe@46 = oaspec@util@string_extra:indent(
_pipe@45,
6,
<<"let key = form_url_decode(raw_key)"/utf8>>
),
_pipe@47 = oaspec@util@string_extra:indent(
_pipe@46,
6,
<<"let value = form_url_decode(raw_value)"/utf8>>
),
_pipe@48 = oaspec@util@string_extra:indent(
_pipe@47,
6,
<<"case dict.get(acc, key) {"/utf8>>
),
_pipe@49 = oaspec@util@string_extra:indent(
_pipe@48,
7,
<<"Ok(existing) -> dict.insert(acc, key, list.append(existing, [value]))"/utf8>>
),
_pipe@50 = oaspec@util@string_extra:indent(
_pipe@49,
7,
<<"Error(_) -> dict.insert(acc, key, [value])"/utf8>>
),
_pipe@51 = oaspec@util@string_extra:indent(
_pipe@50,
6,
<<"}"/utf8>>
),
_pipe@52 = oaspec@util@string_extra:indent(
_pipe@51,
5,
<<"}"/utf8>>
),
_pipe@53 = oaspec@util@string_extra:indent(
_pipe@52,
5,
<<"Error(_) -> {"/utf8>>
),
_pipe@54 = oaspec@util@string_extra:indent(
_pipe@53,
6,
<<"let key = form_url_decode(part)"/utf8>>
),
_pipe@55 = oaspec@util@string_extra:indent(
_pipe@54,
6,
<<"case dict.get(acc, key) {"/utf8>>
),
_pipe@56 = oaspec@util@string_extra:indent(
_pipe@55,
7,
<<"Ok(existing) -> dict.insert(acc, key, list.append(existing, [\"\"]))"/utf8>>
),
_pipe@57 = oaspec@util@string_extra:indent(
_pipe@56,
7,
<<"Error(_) -> dict.insert(acc, key, [\"\"])"/utf8>>
),
_pipe@58 = oaspec@util@string_extra:indent(
_pipe@57,
6,
<<"}"/utf8>>
),
_pipe@59 = oaspec@util@string_extra:indent(
_pipe@58,
5,
<<"}"/utf8>>
),
_pipe@60 = oaspec@util@string_extra:indent(
_pipe@59,
4,
<<"}"/utf8>>
),
_pipe@61 = oaspec@util@string_extra:indent(
_pipe@60,
2,
<<"}"/utf8>>
),
_pipe@62 = oaspec@util@string_extra:indent(
_pipe@61,
1,
<<"})"/utf8>>
),
_pipe@63 = oaspec@util@string_extra:line(_pipe@62, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@63);
false ->
Sb@4
end,
Sb@6 = case Has_multipart_body of
true ->
_pipe@64 = Sb@5,
_pipe@65 = oaspec@util@string_extra:line(
_pipe@64,
<<"fn multipart_boundary(headers: Dict(String, String)) -> Result(String, Nil) {"/utf8>>
),
_pipe@66 = oaspec@util@string_extra:indent(
_pipe@65,
1,
<<"case dict.get(headers, \"content-type\") {"/utf8>>
),
_pipe@67 = oaspec@util@string_extra:indent(
_pipe@66,
2,
<<"Ok(content_type) ->"/utf8>>
),
_pipe@68 = oaspec@util@string_extra:indent(
_pipe@67,
3,
<<"list.find_map(string.split(content_type, \";\"), fn(part) {"/utf8>>
),
_pipe@69 = oaspec@util@string_extra:indent(
_pipe@68,
4,
<<"let trimmed = string.trim(part)"/utf8>>
),
_pipe@70 = oaspec@util@string_extra:indent(
_pipe@69,
4,
<<"case string.starts_with(trimmed, \"boundary=\") {"/utf8>>
),
_pipe@71 = oaspec@util@string_extra:indent(
_pipe@70,
5,
<<"True -> Ok(string.replace(trimmed, \"boundary=\", \"\"))"/utf8>>
),
_pipe@72 = oaspec@util@string_extra:indent(
_pipe@71,
5,
<<"False -> Error(Nil)"/utf8>>
),
_pipe@73 = oaspec@util@string_extra:indent(
_pipe@72,
4,
<<"}"/utf8>>
),
_pipe@74 = oaspec@util@string_extra:indent(
_pipe@73,
3,
<<"})"/utf8>>
),
_pipe@75 = oaspec@util@string_extra:indent(
_pipe@74,
2,
<<"Error(_) -> Error(Nil)"/utf8>>
),
_pipe@76 = oaspec@util@string_extra:indent(
_pipe@75,
1,
<<"}"/utf8>>
),
_pipe@77 = oaspec@util@string_extra:line(_pipe@76, <<"}"/utf8>>),
_pipe@78 = oaspec@util@string_extra:blank_line(_pipe@77),
_pipe@79 = oaspec@util@string_extra:line(
_pipe@78,
<<"fn multipart_name(raw_headers: String) -> Result(String, Nil) {"/utf8>>
),
_pipe@80 = oaspec@util@string_extra:indent(
_pipe@79,
1,
<<"list.find_map(string.split(raw_headers, \"\\r\\n\"), fn(line) {"/utf8>>
),
_pipe@81 = oaspec@util@string_extra:indent(
_pipe@80,
2,
<<"case string.contains(line, \"name=\") {"/utf8>>
),
_pipe@82 = oaspec@util@string_extra:indent(
_pipe@81,
3,
<<"True ->"/utf8>>
),
_pipe@83 = oaspec@util@string_extra:indent(
_pipe@82,
4,
<<"list.find_map(string.split(line, \";\"), fn(part) {"/utf8>>
),
_pipe@84 = oaspec@util@string_extra:indent(
_pipe@83,
5,
<<"let trimmed = string.trim(part)"/utf8>>
),
_pipe@85 = oaspec@util@string_extra:indent(
_pipe@84,
5,
<<"case string.starts_with(trimmed, \"name=\") {"/utf8>>
),
_pipe@86 = oaspec@util@string_extra:indent(
_pipe@85,
6,
<<"True -> Ok(string.replace(string.replace(trimmed, \"name=\", \"\"), \"\\\"\", \"\"))"/utf8>>
),
_pipe@87 = oaspec@util@string_extra:indent(
_pipe@86,
6,
<<"False -> Error(Nil)"/utf8>>
),
_pipe@88 = oaspec@util@string_extra:indent(
_pipe@87,
5,
<<"}"/utf8>>
),
_pipe@89 = oaspec@util@string_extra:indent(
_pipe@88,
4,
<<"})"/utf8>>
),
_pipe@90 = oaspec@util@string_extra:indent(
_pipe@89,
3,
<<"False -> Error(Nil)"/utf8>>
),
_pipe@91 = oaspec@util@string_extra:indent(
_pipe@90,
2,
<<"}"/utf8>>
),
_pipe@92 = oaspec@util@string_extra:indent(
_pipe@91,
1,
<<"})"/utf8>>
),
_pipe@93 = oaspec@util@string_extra:line(_pipe@92, <<"}"/utf8>>),
_pipe@94 = oaspec@util@string_extra:blank_line(_pipe@93),
_pipe@95 = oaspec@util@string_extra:line(
_pipe@94,
<<"fn parse_multipart_body(body: String, headers: Dict(String, String)) -> Dict(String, List(String)) {"/utf8>>
),
_pipe@96 = oaspec@util@string_extra:indent(
_pipe@95,
1,
<<"case multipart_boundary(headers) {"/utf8>>
),
_pipe@97 = oaspec@util@string_extra:indent(
_pipe@96,
2,
<<"Ok(boundary) -> {"/utf8>>
),
_pipe@98 = oaspec@util@string_extra:indent(
_pipe@97,
3,
<<"let delimiter = \"--\" <> boundary"/utf8>>
),
_pipe@99 = oaspec@util@string_extra:indent(
_pipe@98,
3,
<<"let parts = string.split(body, delimiter)"/utf8>>
),
_pipe@100 = oaspec@util@string_extra:indent(
_pipe@99,
3,
<<"list.fold(parts, dict.new(), fn(acc, part) {"/utf8>>
),
_pipe@101 = oaspec@util@string_extra:indent(
_pipe@100,
4,
<<"let normalized_part = part |> string.remove_prefix(\"\\r\\n\") |> string.remove_suffix(\"\\r\\n\")"/utf8>>
),
_pipe@102 = oaspec@util@string_extra:indent(
_pipe@101,
4,
<<"case normalized_part == \"\" || normalized_part == \"--\" {"/utf8>>
),
_pipe@103 = oaspec@util@string_extra:indent(
_pipe@102,
5,
<<"True -> acc"/utf8>>
),
_pipe@104 = oaspec@util@string_extra:indent(
_pipe@103,
5,
<<"False ->"/utf8>>
),
_pipe@105 = oaspec@util@string_extra:indent(
_pipe@104,
6,
<<"case string.split_once(normalized_part, on: \"\\r\\n\\r\\n\") {"/utf8>>
),
_pipe@106 = oaspec@util@string_extra:indent(
_pipe@105,
7,
<<"Ok(#(raw_part_headers, raw_value)) ->"/utf8>>
),
_pipe@107 = oaspec@util@string_extra:indent(
_pipe@106,
8,
<<"case multipart_name(raw_part_headers) {"/utf8>>
),
_pipe@108 = oaspec@util@string_extra:indent(
_pipe@107,
9,
<<"Ok(name) -> {"/utf8>>
),
_pipe@109 = oaspec@util@string_extra:indent(
_pipe@108,
10,
<<"let value = raw_value"/utf8>>
),
_pipe@110 = oaspec@util@string_extra:indent(
_pipe@109,
10,
<<"case dict.get(acc, name) {"/utf8>>
),
_pipe@111 = oaspec@util@string_extra:indent(
_pipe@110,
11,
<<"Ok(existing) -> dict.insert(acc, name, list.append(existing, [value]))"/utf8>>
),
_pipe@112 = oaspec@util@string_extra:indent(
_pipe@111,
11,
<<"Error(_) -> dict.insert(acc, name, [value])"/utf8>>
),
_pipe@113 = oaspec@util@string_extra:indent(
_pipe@112,
10,
<<"}"/utf8>>
),
_pipe@114 = oaspec@util@string_extra:indent(
_pipe@113,
9,
<<"}"/utf8>>
),
_pipe@115 = oaspec@util@string_extra:indent(
_pipe@114,
9,
<<"Error(_) -> acc"/utf8>>
),
_pipe@116 = oaspec@util@string_extra:indent(
_pipe@115,
8,
<<"}"/utf8>>
),
_pipe@117 = oaspec@util@string_extra:indent(
_pipe@116,
7,
<<"Error(_) -> acc"/utf8>>
),
_pipe@118 = oaspec@util@string_extra:indent(
_pipe@117,
6,
<<"}"/utf8>>
),
_pipe@119 = oaspec@util@string_extra:indent(
_pipe@118,
4,
<<"}"/utf8>>
),
_pipe@120 = oaspec@util@string_extra:indent(
_pipe@119,
3,
<<"})"/utf8>>
),
_pipe@121 = oaspec@util@string_extra:indent(
_pipe@120,
2,
<<"}"/utf8>>
),
_pipe@122 = oaspec@util@string_extra:indent(
_pipe@121,
2,
<<"Error(_) -> dict.new()"/utf8>>
),
_pipe@123 = oaspec@util@string_extra:indent(
_pipe@122,
1,
<<"}"/utf8>>
),
_pipe@124 = oaspec@util@string_extra:line(_pipe@123, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@124);
false ->
Sb@5
end,
Sb@7 = case Has_nested_form_urlencoded_body of
true ->
_pipe@125 = Sb@6,
_pipe@126 = oaspec@util@string_extra:line(
_pipe@125,
<<"fn form_object_present(form_body: Dict(String, List(String)), prefix: String, props: List(String)) -> Bool {"/utf8>>
),
_pipe@127 = oaspec@util@string_extra:indent(
_pipe@126,
1,
<<"list.any(props, fn(prop) { dict.has_key(form_body, prefix <> \"[\" <> prop <> \"]\") })"/utf8>>
),
_pipe@128 = oaspec@util@string_extra:line(_pipe@127, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@128);
false ->
Sb@6
end,
Sb@8 = begin
_pipe@129 = Sb@7,
_pipe@130 = oaspec@util@string_extra:doc_comment(
_pipe@129,
<<"Route an incoming request to the appropriate handler."/utf8>>
),
_pipe@131 = oaspec@util@string_extra:line(
_pipe@130,
<<<<<<<<<<<<"pub fn route(method: String, path: List(String), "/utf8,
(route_arg_name(
<<"query"/utf8>>,
Uses_query
))/binary>>/binary,
": Dict(String, List(String)), "/utf8>>/binary,
(route_arg_name(<<"headers"/utf8>>, Uses_headers))/binary>>/binary,
": Dict(String, String), "/utf8>>/binary,
(route_arg_name(<<"body"/utf8>>, Uses_body))/binary>>/binary,
": String) -> ServerResponse {"/utf8>>
),
oaspec@util@string_extra:indent(
_pipe@131,
1,
<<"case method, path {"/utf8>>
)
end,
Sb@10 = gleam@list:fold(
Operations,
Sb@8,
fun(Sb@9, Op@20) ->
{Op_id, Operation@20, Path, Method} = Op@20,
Fn_name = oaspec@util@naming:operation_to_function_name(Op_id),
Method_str = oaspec@openapi@spec:method_to_string(Method),
Path_pattern = path_to_pattern(Path),
Has_params = not gleam@list:is_empty(
erlang:element(6, Operation@20)
)
orelse gleam@option:is_some(erlang:element(7, Operation@20)),
_pipe@132 = Sb@9,
_pipe@133 = oaspec@util@string_extra:indent(
_pipe@132,
2,
<<<<<<<<"\""/utf8, Method_str/binary>>/binary, "\", "/utf8>>/binary,
Path_pattern/binary>>/binary,
" -> {"/utf8>>
),
_pipe@134 = generate_route_body(
_pipe@133,
Op_id,
Fn_name,
Operation@20,
Path,
Has_params,
Ctx
),
oaspec@util@string_extra:indent(_pipe@134, 2, <<"}"/utf8>>)
end
),
Sb@11 = begin
_pipe@135 = Sb@10,
_pipe@136 = oaspec@util@string_extra:indent(
_pipe@135,
2,
<<"_, _ -> ServerResponse(status: 404, body: \"Not Found\", headers: [])"/utf8>>
),
_pipe@137 = oaspec@util@string_extra:indent(_pipe@136, 1, <<"}"/utf8>>),
_pipe@138 = oaspec@util@string_extra:line(_pipe@137, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@138)
end,
Sb@12 = case Needs_cookie_lookup of
true ->
generate_cookie_lookup(Sb@11);
false ->
Sb@11
end,
oaspec@util@string_extra:to_string(Sb@12).
-file("src/oaspec/codegen/server.gleam", 17).
?DOC(" Generate server stub files.\n").
-spec generate(oaspec@codegen@context:context()) -> list(oaspec@codegen@context:generated_file()).
generate(Ctx) ->
Operations = oaspec@openapi@operations:collect_operations(Ctx),
Handlers_content = generate_handlers(Ctx, Operations),
Router_content = generate_router(Ctx, Operations),
[{generated_file,
<<"handlers.gleam"/utf8>>,
Handlers_content,
server_target},
{generated_file, <<"router.gleam"/utf8>>, Router_content, server_target}].