Packages
oaspec
0.48.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@internal@codegen@server.erl
-module(oaspec@internal@codegen@server).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/oaspec/internal/codegen/server.gleam").
-export([generate/1]).
-export_type([header_spec/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.
?MODULEDOC(false).
-type header_spec() :: {header_spec, binary(), binary(), binary(), boolean()}.
-file("src/oaspec/internal/codegen/server.gleam", 137).
?DOC(false).
-spec generate_handler_delegator(
gleam@string_tree:string_tree(),
binary(),
oaspec@internal@openapi@spec:operation(oaspec@internal@openapi@spec:resolved())
) -> gleam@string_tree:string_tree().
generate_handler_delegator(Sb, Op_id, Operation) ->
Fn_name = oaspec@internal@util@naming:operation_to_function_name(Op_id),
Request_type = <<(oaspec@internal@util@naming:schema_to_type_name(Op_id))/binary,
"Request"/utf8>>,
Response_type = <<(oaspec@internal@util@naming:schema_to_type_name(Op_id))/binary,
"Response"/utf8>>,
Has_params = not gleam@list:is_empty(erlang:element(6, Operation)) orelse gleam@option:is_some(
erlang:element(7, Operation)
),
case Has_params of
true ->
_pipe = Sb,
_pipe@1 = oaspec@internal@util@string_extra:line(
_pipe,
<<<<<<<<<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(state: handlers.State, req: request_types."/utf8>>/binary,
Request_type/binary>>/binary,
") -> response_types."/utf8>>/binary,
Response_type/binary>>/binary,
" {"/utf8>>
),
_pipe@2 = oaspec@internal@util@string_extra:indent(
_pipe@1,
1,
<<<<"handlers."/utf8, Fn_name/binary>>/binary,
"(state, req)"/utf8>>
),
_pipe@3 = oaspec@internal@util@string_extra:line(
_pipe@2,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:blank_line(_pipe@3);
false ->
_pipe@4 = Sb,
_pipe@5 = oaspec@internal@util@string_extra:line(
_pipe@4,
<<<<<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(state: handlers.State) -> response_types."/utf8>>/binary,
Response_type/binary>>/binary,
" {"/utf8>>
),
_pipe@6 = oaspec@internal@util@string_extra:indent(
_pipe@5,
1,
<<<<"handlers."/utf8, Fn_name/binary>>/binary, "(state)"/utf8>>
),
_pipe@7 = oaspec@internal@util@string_extra:line(
_pipe@6,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:blank_line(_pipe@7)
end.
-file("src/oaspec/internal/codegen/server.gleam", 114).
?DOC(false).
-spec generate_handlers_generated(
oaspec@internal@codegen@context:context(),
list({binary(),
oaspec@internal@openapi@spec:operation(oaspec@internal@openapi@spec:resolved()),
binary(),
oaspec@internal@openapi@spec:http_method()})
) -> binary().
generate_handlers_generated(Ctx, Operations) ->
Pkg = oaspec@config:package(oaspec@internal@codegen@context:config(Ctx)),
Sb = begin
_pipe = oaspec@internal@util@string_extra:file_header(<<"0.48.0"/utf8>>),
oaspec@internal@util@string_extra:imports(
_pipe,
[<<Pkg/binary, "/handlers"/utf8>>,
<<Pkg/binary, "/request_types"/utf8>>,
<<Pkg/binary, "/response_types"/utf8>>]
)
end,
Sb@2 = gleam@list:fold(
Operations,
Sb,
fun(Sb@1, Op) ->
{Op_id, Operation, _, _} = Op,
generate_handler_delegator(Sb@1, Op_id, Operation)
end
),
oaspec@internal@util@string_extra:to_string(Sb@2).
-file("src/oaspec/internal/codegen/server.gleam", 181).
?DOC(false).
-spec generate_handler(
gleam@string_tree:string_tree(),
binary(),
oaspec@internal@openapi@spec:operation(oaspec@internal@openapi@spec:resolved()),
oaspec@internal@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_handler(Sb, Op_id, Operation, _) ->
Fn_name = oaspec@internal@util@naming:operation_to_function_name(Op_id),
Request_type = <<(oaspec@internal@util@naming:schema_to_type_name(Op_id))/binary,
"Request"/utf8>>,
Response_type = <<(oaspec@internal@util@naming:schema_to_type_name(Op_id))/binary,
"Response"/utf8>>,
Sb@1 = case erlang:element(3, Operation) of
{some, Summary} ->
_pipe = Sb,
oaspec@internal@util@string_extra:doc_comment(_pipe, Summary);
_ ->
Sb
end,
Sb@2 = case erlang:element(4, Operation) of
{some, Desc} ->
_pipe@1 = Sb@1,
oaspec@internal@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@internal@util@string_extra:line(
_pipe@2,
<<<<<<<<<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(state: State, req: request_types."/utf8>>/binary,
Request_type/binary>>/binary,
") -> response_types."/utf8>>/binary,
Response_type/binary>>/binary,
" {"/utf8>>
);
false ->
_pipe@3 = Sb@2,
oaspec@internal@util@string_extra:line(
_pipe@3,
<<<<<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(state: State) -> response_types."/utf8>>/binary,
Response_type/binary>>/binary,
" {"/utf8>>
)
end,
Sb@4 = begin
_pipe@4 = Sb@3,
oaspec@internal@util@string_extra:indent(
_pipe@4,
1,
<<"let _ = state"/utf8>>
)
end,
Sb@5 = case Has_params of
true ->
_pipe@5 = Sb@4,
oaspec@internal@util@string_extra:indent(
_pipe@5,
1,
<<"let _ = req"/utf8>>
);
false ->
Sb@4
end,
_pipe@6 = Sb@5,
_pipe@7 = oaspec@internal@util@string_extra:indent(
_pipe@6,
1,
<<<<"panic as \"unimplemented: "/utf8, Fn_name/binary>>/binary,
"\""/utf8>>
),
_pipe@8 = oaspec@internal@util@string_extra:line(_pipe@7, <<"}"/utf8>>),
oaspec@internal@util@string_extra:blank_line(_pipe@8).
-file("src/oaspec/internal/codegen/server.gleam", 67).
?DOC(false).
-spec generate_handlers(
oaspec@internal@codegen@context:context(),
list({binary(),
oaspec@internal@openapi@spec:operation(oaspec@internal@openapi@spec:resolved()),
binary(),
oaspec@internal@openapi@spec:http_method()})
) -> binary().
generate_handlers(Ctx, Operations) ->
Sb = begin
_pipe = oaspec@internal@util@string_extra:line(
oaspec@internal@util@string_extra:new(),
<<"//// Implement these handler functions. This file is emitted once"/utf8>>
),
_pipe@1 = oaspec@internal@util@string_extra:line(
_pipe,
<<"//// by `oaspec generate` and skipped on subsequent runs, so your"/utf8>>
),
_pipe@2 = oaspec@internal@util@string_extra:line(
_pipe@1,
<<"//// edits survive regeneration. Router wiring lives in"/utf8>>
),
_pipe@3 = oaspec@internal@util@string_extra:line(
_pipe@2,
<<"//// `handlers_generated.gleam`, which delegates here."/utf8>>
),
_pipe@4 = oaspec@internal@util@string_extra:blank_line(_pipe@3),
_pipe@5 = oaspec@internal@util@string_extra:imports(
_pipe@4,
[<<(oaspec@config:package(
oaspec@internal@codegen@context:config(Ctx)
))/binary,
"/request_types"/utf8>>,
<<(oaspec@config:package(
oaspec@internal@codegen@context:config(Ctx)
))/binary,
"/response_types"/utf8>>]
),
_pipe@6 = oaspec@internal@util@string_extra:doc_comment(
_pipe@5,
<<"Application state passed to every handler."/utf8>>
),
_pipe@7 = oaspec@internal@util@string_extra:doc_comment(
_pipe@6,
<<"Add fields here for DB connections, config, loggers, etc. Construct a value of this type in your `main` and pass it to `router.route` as the first argument."/utf8>>
),
_pipe@8 = oaspec@internal@util@string_extra:line(
_pipe@7,
<<"pub type State {"/utf8>>
),
_pipe@9 = oaspec@internal@util@string_extra:indent(
_pipe@8,
1,
<<"State"/utf8>>
),
_pipe@10 = oaspec@internal@util@string_extra:line(_pipe@9, <<"}"/utf8>>),
oaspec@internal@util@string_extra:blank_line(_pipe@10)
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
),
oaspec@internal@util@string_extra:to_string(Sb@2).
-file("src/oaspec/internal/codegen/server.gleam", 367).
?DOC(false).
-spec route_arg_name(binary(), boolean()) -> binary().
route_arg_name(Name, Used) ->
gleam@bool:guard(Used, Name, fun() -> <<"_"/utf8, Name/binary>> end).
-file("src/oaspec/internal/codegen/server.gleam", 372).
?DOC(false).
-spec generate_cookie_lookup(gleam@string_tree:string_tree()) -> gleam@string_tree:string_tree().
generate_cookie_lookup(Sb) ->
_pipe = Sb,
_pipe@1 = oaspec@internal@util@string_extra:doc_comment(
_pipe,
<<"Extract a cookie value from the Cookie header."/utf8>>
),
oaspec@internal@util@string_extra:raw(
_pipe@1,
<<"fn cookie_lookup(headers: Dict(String, String), key: String) -> Result(String, Nil) {
case dict.get(headers, \"cookie\") {
Ok(raw) ->
list.find_map(string.split(raw, \";\"), fn(part) {
let trimmed = string.trim(part)
case string.split_once(trimmed, on: \"=\") {
Ok(#(cookie_key, cookie_value)) ->
case string.trim(cookie_key) == key {
True -> uri.percent_decode(string.trim(cookie_value))
False -> Error(Nil)
}
Error(_) -> Error(Nil)
}
})
Error(_) -> Error(Nil)
}
}
"/utf8>>
).
-file("src/oaspec/internal/codegen/server.gleam", 771).
?DOC(false).
-spec query_param_explode_array(
oaspec@internal@openapi@spec:parameter(oaspec@internal@openapi@spec:resolved())
) -> boolean().
query_param_explode_array(P) ->
case oaspec@internal@openapi@spec:parameter_schema(P) of
{some, {inline, {array_schema, _, _, _, _, _}}} ->
case erlang:element(8, P) of
{some, false} ->
false;
_ ->
true
end;
_ ->
false
end.
-file("src/oaspec/internal/codegen/server.gleam", 851).
?DOC(false).
-spec array_int_parse_expr(
binary(),
oaspec@internal@openapi@spec:parameter(oaspec@internal@openapi@spec:resolved()),
binary()
) -> binary().
array_int_parse_expr(Raw_var, P, Delim) ->
case erlang:element(8, P) of
{some, false} ->
<<<<<<<<"list.try_map(list.map(string.split("/utf8, Raw_var/binary>>/binary,
", \""/utf8>>/binary,
Delim/binary>>/binary,
"\"), string.trim), int.parse)"/utf8>>;
_ ->
<<<<"list.try_map(list.map("/utf8, Raw_var/binary>>/binary,
", string.trim), int.parse)"/utf8>>
end.
-file("src/oaspec/internal/codegen/server.gleam", 867).
?DOC(false).
-spec array_float_parse_expr(
binary(),
oaspec@internal@openapi@spec:parameter(oaspec@internal@openapi@spec:resolved()),
binary()
) -> binary().
array_float_parse_expr(Raw_var, P, Delim) ->
case erlang:element(8, P) of
{some, false} ->
<<<<<<<<"list.try_map(list.map(string.split("/utf8, Raw_var/binary>>/binary,
", \""/utf8>>/binary,
Delim/binary>>/binary,
"\"), string.trim), float.parse)"/utf8>>;
_ ->
<<<<"list.try_map(list.map("/utf8, Raw_var/binary>>/binary,
", string.trim), float.parse)"/utf8>>
end.
-file("src/oaspec/internal/codegen/server.gleam", 788).
?DOC(false).
-spec query_required_open_parse_case(
gleam@string_tree:string_tree(),
oaspec@internal@openapi@spec:parameter(oaspec@internal@openapi@spec:resolved()),
oaspec@internal@codegen@context:context()
) -> gleam@string_tree:string_tree().
query_required_open_parse_case(Sb, P, Ctx) ->
Raw_var = <<(oaspec@internal@util@naming:to_snake_case(erlang:element(2, P)))/binary,
"_raw"/utf8>>,
Delim = case erlang:element(7, P) of
{some, pipe_delimited_style} ->
<<"|"/utf8>>;
{some, space_delimited_style} ->
<<" "/utf8>>;
_ ->
<<","/utf8>>
end,
case oaspec@internal@openapi@spec:parameter_schema(P) of
{some, {inline, {integer_schema, _, _, _, _, _, _, _}}} ->
_pipe = Sb,
_pipe@1 = oaspec@internal@util@string_extra:indent(
_pipe,
3,
<<<<"case int.parse("/utf8, Raw_var/binary>>/binary,
") {"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@1,
4,
<<<<"Ok("/utf8, Raw_var/binary>>/binary, "_parsed) -> {"/utf8>>
);
{some, {inline, {number_schema, _, _, _, _, _, _, _}}} ->
_pipe@2 = Sb,
_pipe@3 = oaspec@internal@util@string_extra:indent(
_pipe@2,
3,
<<<<"case float.parse("/utf8, Raw_var/binary>>/binary,
") {"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@3,
4,
<<<<"Ok("/utf8, Raw_var/binary>>/binary, "_parsed) -> {"/utf8>>
);
{some,
{inline,
{array_schema,
_,
{inline, {integer_schema, _, _, _, _, _, _, _}},
_,
_,
_}}} ->
Parse_expr = array_int_parse_expr(Raw_var, P, Delim),
_pipe@4 = Sb,
_pipe@5 = oaspec@internal@util@string_extra:indent(
_pipe@4,
3,
<<<<"case "/utf8, Parse_expr/binary>>/binary, " {"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@5,
4,
<<<<"Ok("/utf8, Raw_var/binary>>/binary,
"_parsed_list) -> {"/utf8>>
);
{some,
{inline,
{array_schema,
_,
{inline, {number_schema, _, _, _, _, _, _, _}},
_,
_,
_}}} ->
Parse_expr@1 = array_float_parse_expr(Raw_var, P, Delim),
_pipe@6 = Sb,
_pipe@7 = oaspec@internal@util@string_extra:indent(
_pipe@6,
3,
<<<<"case "/utf8, Parse_expr@1/binary>>/binary, " {"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@7,
4,
<<<<"Ok("/utf8, Raw_var/binary>>/binary,
"_parsed_list) -> {"/utf8>>
);
{some, Ref} ->
case oaspec@internal@codegen@server_request_decode:schema_ref_string_enum(
Ref,
Ctx
) of
{some, {Type_name, Values}} ->
_pipe@8 = Sb,
_pipe@9 = oaspec@internal@util@string_extra:indent(
_pipe@8,
3,
<<<<"case "/utf8,
(oaspec@internal@codegen@server_request_decode:enum_match_result_expr(
Raw_var,
Type_name,
Values
))/binary>>/binary,
" {"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@9,
4,
<<<<"Ok("/utf8, Raw_var/binary>>/binary,
"_parsed) -> {"/utf8>>
);
none ->
Sb
end;
_ ->
Sb
end.
-file("src/oaspec/internal/codegen/server.gleam", 925).
?DOC(false).
-spec single_value_required_open_parse_case(
gleam@string_tree:string_tree(),
oaspec@internal@openapi@spec:parameter(oaspec@internal@openapi@spec:resolved())
) -> gleam@string_tree:string_tree().
single_value_required_open_parse_case(Sb, P) ->
Raw_var = <<(oaspec@internal@util@naming:to_snake_case(erlang:element(2, P)))/binary,
"_raw"/utf8>>,
case oaspec@internal@openapi@spec:parameter_schema(P) of
{some, {inline, {integer_schema, _, _, _, _, _, _, _}}} ->
_pipe = Sb,
_pipe@1 = oaspec@internal@util@string_extra:indent(
_pipe,
3,
<<<<"case int.parse("/utf8, Raw_var/binary>>/binary,
") {"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@1,
4,
<<<<"Ok("/utf8, Raw_var/binary>>/binary, "_parsed) -> {"/utf8>>
);
{some, {inline, {number_schema, _, _, _, _, _, _, _}}} ->
_pipe@2 = Sb,
_pipe@3 = oaspec@internal@util@string_extra:indent(
_pipe@2,
3,
<<<<"case float.parse("/utf8, Raw_var/binary>>/binary,
") {"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@3,
4,
<<<<"Ok("/utf8, Raw_var/binary>>/binary, "_parsed) -> {"/utf8>>
);
{some,
{inline,
{array_schema,
_,
{inline, {integer_schema, _, _, _, _, _, _, _}},
_,
_,
_}}} ->
_pipe@4 = Sb,
_pipe@5 = oaspec@internal@util@string_extra:indent(
_pipe@4,
3,
<<<<"case list.try_map(list.map(string.split("/utf8,
Raw_var/binary>>/binary,
", \",\"), string.trim), int.parse) {"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@5,
4,
<<<<"Ok("/utf8, Raw_var/binary>>/binary,
"_parsed_list) -> {"/utf8>>
);
{some,
{inline,
{array_schema,
_,
{inline, {number_schema, _, _, _, _, _, _, _}},
_,
_,
_}}} ->
_pipe@6 = Sb,
_pipe@7 = oaspec@internal@util@string_extra:indent(
_pipe@6,
3,
<<<<"case list.try_map(list.map(string.split("/utf8,
Raw_var/binary>>/binary,
", \",\"), string.trim), float.parse) {"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@7,
4,
<<<<"Ok("/utf8, Raw_var/binary>>/binary,
"_parsed_list) -> {"/utf8>>
);
_ ->
Sb
end.
-file("src/oaspec/internal/codegen/server.gleam", 1016).
?DOC(false).
-spec problem_response_expr(integer(), binary()) -> binary().
problem_response_expr(Status, Detail) ->
Body = <<<<"\"{\\\"type\\\":\\\"about:blank\\\",\\\"title\\\":\\\""/utf8,
Detail/binary>>/binary,
"\\\"}\""/utf8>>,
<<<<<<<<"ServerResponse(status: "/utf8,
(erlang:integer_to_binary(Status))/binary>>/binary,
", body: TextBody("/utf8>>/binary,
Body/binary>>/binary,
"), headers: [#(\"content-type\", \"application/problem+json\")])"/utf8>>.
-file("src/oaspec/internal/codegen/server.gleam", 884).
?DOC(false).
-spec close_query_required_parse_case(
gleam@string_tree:string_tree(),
oaspec@internal@openapi@spec:parameter(oaspec@internal@openapi@spec:resolved()),
oaspec@internal@codegen@context:context()
) -> gleam@string_tree:string_tree().
close_query_required_parse_case(Sb, P, Ctx) ->
Close = fun(Sb@1) -> _pipe = Sb@1,
_pipe@1 = oaspec@internal@util@string_extra:indent(
_pipe,
4,
<<"}"/utf8>>
),
_pipe@2 = oaspec@internal@util@string_extra:indent(
_pipe@1,
4,
<<"_ -> "/utf8,
(problem_response_expr(400, <<"invalid query parameter"/utf8>>))/binary>>
),
oaspec@internal@util@string_extra:indent(_pipe@2, 3, <<"}"/utf8>>) end,
case oaspec@internal@openapi@spec:parameter_schema(P) of
{some, {inline, {integer_schema, _, _, _, _, _, _, _}}} ->
Close(Sb);
{some, {inline, {number_schema, _, _, _, _, _, _, _}}} ->
Close(Sb);
{some,
{inline,
{array_schema,
_,
{inline, {integer_schema, _, _, _, _, _, _, _}},
_,
_,
_}}} ->
Close(Sb);
{some,
{inline,
{array_schema,
_,
{inline, {number_schema, _, _, _, _, _, _, _}},
_,
_,
_}}} ->
Close(Sb);
{some, Ref} ->
case oaspec@internal@codegen@server_request_decode:schema_ref_string_enum(
Ref,
Ctx
) of
{some, _} ->
Close(Sb);
none ->
Sb
end;
_ ->
Sb
end.
-file("src/oaspec/internal/codegen/server.gleam", 967).
?DOC(false).
-spec close_single_value_required_parse_case(
gleam@string_tree:string_tree(),
oaspec@internal@openapi@spec:parameter(oaspec@internal@openapi@spec:resolved()),
oaspec@internal@codegen@context:context()
) -> gleam@string_tree:string_tree().
close_single_value_required_parse_case(Sb, P, Ctx) ->
Close = fun(Sb@1) -> _pipe = Sb@1,
_pipe@1 = oaspec@internal@util@string_extra:indent(
_pipe,
4,
<<"}"/utf8>>
),
_pipe@2 = oaspec@internal@util@string_extra:indent(
_pipe@1,
4,
<<"_ -> "/utf8,
(problem_response_expr(400, <<"invalid header or cookie"/utf8>>))/binary>>
),
oaspec@internal@util@string_extra:indent(_pipe@2, 3, <<"}"/utf8>>) end,
case oaspec@internal@openapi@spec:parameter_schema(P) of
{some, {inline, {integer_schema, _, _, _, _, _, _, _}}} ->
Close(Sb);
{some, {inline, {number_schema, _, _, _, _, _, _, _}}} ->
Close(Sb);
{some,
{inline,
{array_schema,
_,
{inline, {integer_schema, _, _, _, _, _, _, _}},
_,
_,
_}}} ->
Close(Sb);
{some,
{inline,
{array_schema,
_,
{inline, {number_schema, _, _, _, _, _, _, _}},
_,
_,
_}}} ->
Close(Sb);
{some, Ref} ->
case oaspec@internal@codegen@server_request_decode:schema_ref_string_enum(
Ref,
Ctx
) of
{some, _} ->
Close(Sb);
none ->
Sb
end;
_ ->
Sb
end.
-file("src/oaspec/internal/codegen/server.gleam", 1031).
?DOC(false).
-spec close_lookup_case(gleam@string_tree:string_tree()) -> gleam@string_tree:string_tree().
close_lookup_case(Sb) ->
_pipe = Sb,
_pipe@1 = oaspec@internal@util@string_extra:indent(_pipe, 4, <<"}"/utf8>>),
_pipe@2 = oaspec@internal@util@string_extra:indent(
_pipe@1,
4,
<<"_ -> "/utf8,
(problem_response_expr(400, <<"missing or invalid parameter"/utf8>>))/binary>>
),
oaspec@internal@util@string_extra:indent(_pipe@2, 3, <<"}"/utf8>>).
-file("src/oaspec/internal/codegen/server.gleam", 1268).
?DOC(false).
-spec response_header_field_type(
gleam@option:option(oaspec@internal@openapi@schema:schema_ref())
) -> binary().
response_header_field_type(Schema_opt) ->
case Schema_opt of
{some, {inline, {integer_schema, _, _, _, _, _, _, _}}} ->
<<"Int"/utf8>>;
{some, {inline, {number_schema, _, _, _, _, _, _, _}}} ->
<<"Float"/utf8>>;
{some, {inline, {boolean_schema, _}}} ->
<<"Bool"/utf8>>;
{some, {inline, {string_schema, _, _, _, _, _, _}}} ->
<<"String"/utf8>>;
{some, {reference, _, Name}} ->
<<"types."/utf8,
(oaspec@internal@util@naming:schema_to_type_name(Name))/binary>>;
_ ->
<<"String"/utf8>>
end.
-file("src/oaspec/internal/codegen/server.gleam", 1246).
?DOC(false).
-spec sorted_header_specs(
gleam@dict:dict(binary(), oaspec@internal@openapi@spec:header())
) -> list(header_spec()).
sorted_header_specs(Headers) ->
_pipe = Headers,
_pipe@1 = maps:to_list(_pipe),
_pipe@2 = gleam@list:sort(
_pipe@1,
fun(A, B) ->
gleam@string:compare(erlang:element(1, A), erlang:element(1, B))
end
),
gleam@list:map(
_pipe@2,
fun(Entry) ->
{Header_name, Header} = Entry,
Field_name = oaspec@internal@util@naming:to_snake_case(Header_name),
Field_type = response_header_field_type(erlang:element(4, Header)),
{header_spec,
Header_name,
Field_name,
Field_type,
erlang:element(3, Header)}
end
).
-file("src/oaspec/internal/codegen/server.gleam", 1352).
?DOC(false).
-spec append_chunks(binary(), list(binary())) -> binary().
append_chunks(Prefix, Header_chunks) ->
case Header_chunks of
[] ->
Prefix;
_ ->
case Prefix of
<<""/utf8>> ->
gleam@string:join(Header_chunks, <<", "/utf8>>);
_ ->
<<<<Prefix/binary, ", "/utf8>>/binary,
(gleam@string:join(Header_chunks, <<", "/utf8>>))/binary>>
end
end.
-file("src/oaspec/internal/codegen/server.gleam", 1395).
?DOC(false).
-spec stringify_header_value(binary(), binary()) -> binary().
stringify_header_value(Field_type, Value_expr) ->
case Field_type of
<<"Int"/utf8>> ->
<<<<"int.to_string("/utf8, Value_expr/binary>>/binary, ")"/utf8>>;
<<"Float"/utf8>> ->
<<<<"float.to_string("/utf8, Value_expr/binary>>/binary, ")"/utf8>>;
<<"Bool"/utf8>> ->
<<<<"bool.to_string("/utf8, Value_expr/binary>>/binary, ")"/utf8>>;
_ ->
Value_expr
end.
-file("src/oaspec/internal/codegen/server.gleam", 1371).
?DOC(false).
-spec header_chunk_expr(header_spec()) -> binary().
header_chunk_expr(Spec) ->
Render_value = fun(Value_expr) ->
<<<<<<<<"[#(\""/utf8, (erlang:element(2, Spec))/binary>>/binary,
"\", "/utf8>>/binary,
(stringify_header_value(erlang:element(4, Spec), Value_expr))/binary>>/binary,
")]"/utf8>>
end,
case erlang:element(5, Spec) of
true ->
Render_value(<<"hdrs."/utf8, (erlang:element(3, Spec))/binary>>);
false ->
<<<<<<<<"case hdrs."/utf8, (erlang:element(3, Spec))/binary>>/binary,
" { Some(v) -> "/utf8>>/binary,
(Render_value(<<"v"/utf8>>))/binary>>/binary,
" None -> [] }"/utf8>>
end.
-file("src/oaspec/internal/codegen/server.gleam", 1329).
?DOC(false).
-spec headers_slot_expr(gleam@option:option(binary()), list(header_spec())) -> binary().
headers_slot_expr(Content_type_header, Header_specs) ->
Content_type_chunk = case Content_type_header of
{some, Media_type_name} ->
[<<<<"[#(\"content-type\", \""/utf8, Media_type_name/binary>>/binary,
"\")]"/utf8>>];
none ->
[]
end,
Header_chunks = gleam@list:map(
Header_specs,
fun(Spec) -> header_chunk_expr(Spec) end
),
case {Content_type_chunk, Header_chunks} of
{[], []} ->
<<"[]"/utf8>>;
{[Single_chunk], []} ->
Single_chunk;
{_, _} ->
<<<<"list.flatten(["/utf8,
(begin
_pipe = gleam@string:join(
Content_type_chunk,
<<", "/utf8>>
),
append_chunks(_pipe, Header_chunks)
end)/binary>>/binary,
"])"/utf8>>
end.
-file("src/oaspec/internal/codegen/server.gleam", 1287).
?DOC(false).
-spec emit_response_arm(
gleam@string_tree:string_tree(),
binary(),
binary(),
boolean(),
boolean(),
binary(),
gleam@option:option(binary()),
list(header_spec())
) -> gleam@string_tree:string_tree().
emit_response_arm(
Sb,
Variant_name,
Status_int,
Has_data,
Has_headers,
Body_expr,
Content_type_header,
Header_specs
) ->
Pattern_args = case {Has_data, Has_headers} of
{true, true} ->
<<"(data, hdrs)"/utf8>>;
{true, false} ->
<<"(data)"/utf8>>;
{false, true} ->
<<"(hdrs)"/utf8>>;
{false, false} ->
<<""/utf8>>
end,
Headers_expr = headers_slot_expr(Content_type_header, Header_specs),
_pipe = Sb,
oaspec@internal@util@string_extra:indent(
_pipe,
4,
<<<<<<<<<<<<<<<<<<"response_types."/utf8, Variant_name/binary>>/binary,
Pattern_args/binary>>/binary,
" -> ServerResponse(status: "/utf8>>/binary,
Status_int/binary>>/binary,
", body: "/utf8>>/binary,
Body_expr/binary>>/binary,
", headers: "/utf8>>/binary,
Headers_expr/binary>>/binary,
")"/utf8>>
).
-file("src/oaspec/internal/codegen/server.gleam", 1405).
?DOC(false).
-spec get_encode_function(
gleam@option:option(oaspec@internal@openapi@schema:schema_ref()),
oaspec@internal@codegen@context:context()
) -> binary().
get_encode_function(Schema_ref, _) ->
case Schema_ref of
{some, {reference, _, Name}} ->
<<<<"encode.encode_"/utf8,
(oaspec@internal@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@internal@util@naming:to_snake_case(Name@1))/binary>>/binary,
"_json) }"/utf8>>;
{inline, {string_schema, _, _, _, _, _, _}} ->
<<"fn(items) { json.array(items, json.string) }"/utf8>>;
{inline, {integer_schema, _, _, _, _, _, _, _}} ->
<<"fn(items) { json.array(items, json.int) }"/utf8>>;
{inline, {number_schema, _, _, _, _, _, _, _}} ->
<<"fn(items) { json.array(items, json.float) }"/utf8>>;
{inline, {boolean_schema, _}} ->
<<"fn(items) { json.array(items, json.bool) }"/utf8>>;
_ ->
<<"fn(items) { json.array(items, 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/internal/codegen/server.gleam", 1045).
?DOC(false).
-spec generate_response_conversion(
gleam@string_tree:string_tree(),
binary(),
oaspec@internal@openapi@spec:operation(oaspec@internal@openapi@spec:resolved()),
oaspec@internal@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_response_conversion(Sb, Response_type_name, Operation, Ctx) ->
Responses = oaspec@internal@util@http:sort_response_entries(
maps:to_list(erlang:element(8, Operation))
),
case gleam@list:is_empty(Responses) of
true ->
_pipe = Sb,
oaspec@internal@util@string_extra:indent(
_pipe,
3,
<<"ServerResponse(status: 200, body: EmptyBody, headers: [])"/utf8>>
);
false ->
Sb@1 = begin
_pipe@1 = Sb,
oaspec@internal@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@internal@util@http:status_code_suffix(
Status_code
))/binary>>,
Status_int = oaspec@internal@util@http:status_code_to_int(
Status_code
),
Content_entries = maps:to_list(
erlang:element(3, Response)
),
Header_specs = sorted_header_specs(
erlang:element(4, Response)
),
Has_headers = not gleam@list:is_empty(Header_specs),
case Content_entries of
[] ->
emit_response_arm(
Sb@2,
Variant_name,
Status_int,
false,
Has_headers,
<<"EmptyBody"/utf8>>,
none,
Header_specs
);
[{Media_type_name, Media_type}] ->
case oaspec@internal@util@content_type:from_string(
Media_type_name
) of
application_json ->
case erlang:element(2, Media_type) of
{some, _} ->
Encode_fn = get_encode_function(
erlang:element(
2,
Media_type
),
Ctx
),
emit_response_arm(
Sb@2,
Variant_name,
Status_int,
true,
Has_headers,
<<<<"TextBody(json.to_string("/utf8,
Encode_fn/binary>>/binary,
"(data)))"/utf8>>,
{some, Media_type_name},
Header_specs
);
none ->
emit_response_arm(
Sb@2,
Variant_name,
Status_int,
false,
Has_headers,
<<"EmptyBody"/utf8>>,
none,
Header_specs
)
end;
text_plain ->
case erlang:element(2, Media_type) of
{some, _} ->
emit_response_arm(
Sb@2,
Variant_name,
Status_int,
true,
Has_headers,
<<"TextBody(data)"/utf8>>,
{some, Media_type_name},
Header_specs
);
none ->
emit_response_arm(
Sb@2,
Variant_name,
Status_int,
false,
Has_headers,
<<"EmptyBody"/utf8>>,
none,
Header_specs
)
end;
application_xml ->
case erlang:element(2, Media_type) of
{some, _} ->
emit_response_arm(
Sb@2,
Variant_name,
Status_int,
true,
Has_headers,
<<"TextBody(data)"/utf8>>,
{some, Media_type_name},
Header_specs
);
none ->
emit_response_arm(
Sb@2,
Variant_name,
Status_int,
false,
Has_headers,
<<"EmptyBody"/utf8>>,
none,
Header_specs
)
end;
text_xml ->
case erlang:element(2, Media_type) of
{some, _} ->
emit_response_arm(
Sb@2,
Variant_name,
Status_int,
true,
Has_headers,
<<"TextBody(data)"/utf8>>,
{some, Media_type_name},
Header_specs
);
none ->
emit_response_arm(
Sb@2,
Variant_name,
Status_int,
false,
Has_headers,
<<"EmptyBody"/utf8>>,
none,
Header_specs
)
end;
application_octet_stream ->
case erlang:element(2, Media_type) of
{some, _} ->
emit_response_arm(
Sb@2,
Variant_name,
Status_int,
true,
Has_headers,
<<"BytesBody(data)"/utf8>>,
{some, Media_type_name},
Header_specs
);
none ->
emit_response_arm(
Sb@2,
Variant_name,
Status_int,
false,
Has_headers,
<<"EmptyBody"/utf8>>,
none,
Header_specs
)
end;
_ ->
case erlang:element(2, Media_type) of
{some, _} ->
Encode_fn@1 = get_encode_function(
erlang:element(
2,
Media_type
),
Ctx
),
emit_response_arm(
Sb@2,
Variant_name,
Status_int,
true,
Has_headers,
<<<<"TextBody(json.to_string("/utf8,
Encode_fn@1/binary>>/binary,
"(data)))"/utf8>>,
{some, Media_type_name},
Header_specs
);
none ->
emit_response_arm(
Sb@2,
Variant_name,
Status_int,
false,
Has_headers,
<<"EmptyBody"/utf8>>,
none,
Header_specs
)
end
end;
[{First_media_type, _}, _ | _] ->
emit_response_arm(
Sb@2,
Variant_name,
Status_int,
true,
Has_headers,
<<"TextBody(data)"/utf8>>,
{some, First_media_type},
Header_specs
)
end;
_ ->
Sb@2
end
end
),
_pipe@2 = Sb@3,
oaspec@internal@util@string_extra:indent(_pipe@2, 3, <<"}"/utf8>>)
end.
-file("src/oaspec/internal/codegen/server.gleam", 422).
?DOC(false).
-spec generate_safe_request_and_dispatch(
gleam@string_tree:string_tree(),
binary(),
binary(),
binary(),
binary(),
oaspec@internal@openapi@spec:operation(oaspec@internal@openapi@spec:resolved()),
binary(),
oaspec@internal@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_safe_request_and_dispatch(
Sb,
Request_type_name,
Response_type_name,
Op_id,
Fn_name,
Operation,
_,
Ctx
) ->
Params = gleam@list:filter_map(
erlang:element(6, Operation),
fun(R) -> case R of
{value, P} ->
{ok, P};
_ ->
{error, nil}
end end
),
Deduped_field_names = oaspec@internal@openapi@dedup:dedup_param_field_names(
Params
),
Params_with_field_names = gleam@list:zip(Params, Deduped_field_names),
Path_params_needing_parse = gleam@list:filter(
Params,
fun(P@1) ->
(erlang:element(3, P@1) =:= in_path) andalso oaspec@internal@codegen@server_request_decode:param_needs_result_unwrap(
P@1
)
end
),
Required_query_params = gleam@list:filter(
Params,
fun(P@2) ->
((erlang:element(3, P@2) =:= in_query) andalso erlang:element(
5,
P@2
))
andalso not oaspec@internal@codegen@server_request_decode:is_deep_object_param(
P@2,
Ctx
)
end
),
Required_header_params = gleam@list:filter(
Params,
fun(P@3) ->
(erlang:element(3, P@3) =:= in_header) andalso erlang:element(
5,
P@3
)
end
),
Required_cookie_params = gleam@list:filter(
Params,
fun(P@4) ->
(erlang:element(3, P@4) =:= in_cookie) andalso erlang:element(
5,
P@4
)
end
),
Needs_body_guard = case erlang:element(7, Operation) of
{some, {value, Rb}} ->
erlang:element(4, Rb) andalso gleam@list:any(
maps:to_list(erlang:element(3, Rb)),
fun(Entry) ->
oaspec@internal@util@content_type:is_json_compatible(
erlang:element(1, Entry)
)
end
);
_ ->
false
end,
Sb@2 = gleam@list:fold(
Path_params_needing_parse,
Sb,
fun(Sb@1, P@5) ->
Var_name = oaspec@internal@util@naming:to_snake_case(
erlang:element(2, P@5)
),
Parse_expr = oaspec@internal@codegen@server_request_decode:param_parse_expr(
Var_name,
P@5
),
_pipe = Sb@1,
_pipe@1 = oaspec@internal@util@string_extra:indent(
_pipe,
3,
<<<<"case "/utf8, Parse_expr/binary>>/binary, " {"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@1,
4,
<<<<"Ok("/utf8, Var_name/binary>>/binary, "_parsed) -> {"/utf8>>
)
end
),
Sb@4 = gleam@list:fold(
Required_query_params,
Sb@2,
fun(Sb@3, P@6) ->
Raw_var = <<(oaspec@internal@util@naming:to_snake_case(
erlang:element(2, P@6)
))/binary,
"_raw"/utf8>>,
Pattern = case query_param_explode_array(P@6) of
true ->
<<<<"Ok([_, ..] as "/utf8, Raw_var/binary>>/binary,
")"/utf8>>;
false ->
<<<<"Ok(["/utf8, Raw_var/binary>>/binary, ", ..])"/utf8>>
end,
_pipe@2 = Sb@3,
_pipe@3 = oaspec@internal@util@string_extra:indent(
_pipe@2,
3,
<<<<"case dict.get(query, \""/utf8,
(erlang:element(2, P@6))/binary>>/binary,
"\") {"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@3,
4,
<<Pattern/binary, " -> {"/utf8>>
)
end
),
Sb@6 = gleam@list:fold(
Required_query_params,
Sb@4,
fun(Sb@5, P@7) -> query_required_open_parse_case(Sb@5, P@7, Ctx) end
),
Sb@8 = gleam@list:fold(
Required_header_params,
Sb@6,
fun(Sb@7, P@8) ->
Raw_var@1 = <<(oaspec@internal@util@naming:to_snake_case(
erlang:element(2, P@8)
))/binary,
"_raw"/utf8>>,
Key = string:lowercase(erlang:element(2, P@8)),
_pipe@4 = Sb@7,
_pipe@5 = oaspec@internal@util@string_extra:indent(
_pipe@4,
3,
<<<<"case dict.get(headers, \""/utf8, Key/binary>>/binary,
"\") {"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@5,
4,
<<<<"Ok("/utf8, Raw_var@1/binary>>/binary, ") -> {"/utf8>>
)
end
),
Sb@10 = gleam@list:fold(
Required_header_params,
Sb@8,
fun(Sb@9, P@9) -> single_value_required_open_parse_case(Sb@9, P@9) end
),
Sb@12 = gleam@list:fold(
Required_cookie_params,
Sb@10,
fun(Sb@11, P@10) ->
Raw_var@2 = <<(oaspec@internal@util@naming:to_snake_case(
erlang:element(2, P@10)
))/binary,
"_raw"/utf8>>,
_pipe@6 = Sb@11,
_pipe@7 = oaspec@internal@util@string_extra:indent(
_pipe@6,
3,
<<<<"case cookie_lookup(headers, \""/utf8,
(erlang:element(2, P@10))/binary>>/binary,
"\") {"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@7,
4,
<<<<"Ok("/utf8, Raw_var@2/binary>>/binary, ") -> {"/utf8>>
)
end
),
Sb@14 = gleam@list:fold(
Required_cookie_params,
Sb@12,
fun(Sb@13, P@11) ->
single_value_required_open_parse_case(Sb@13, P@11)
end
),
Body_schema_ref_name = case erlang:element(7, Operation) of
{some, {value, Rb@1}} ->
Content_entries = maps:to_list(erlang:element(3, Rb@1)),
case Content_entries of
[{_, Media_type}] ->
case erlang:element(2, Media_type) of
{some, {reference, _, Name}} ->
{some, Name};
_ ->
none
end;
_ ->
none
end;
_ ->
none
end,
Needs_guard_validation = (oaspec@config:validate(
oaspec@internal@codegen@context:config(Ctx)
)
andalso Needs_body_guard)
andalso (case Body_schema_ref_name of
{some, Name@1} ->
oaspec@internal@codegen@guards:schema_has_validator(Name@1, Ctx);
none ->
false
end),
Sb@15 = case {Needs_body_guard, erlang:element(7, Operation)} of
{true, {some, {value, Rb@2}}} ->
Content_entries@1 = maps:to_list(erlang:element(3, Rb@2)),
case Content_entries@1 of
[{_, Media_type@1}] ->
case erlang:element(2, Media_type@1) of
{some, {reference, _, Name@2}} ->
Decode_fn = <<<<"decode.decode_"/utf8,
(oaspec@internal@util@naming:to_snake_case(
Name@2
))/binary>>/binary,
"(body)"/utf8>>,
_pipe@8 = Sb@14,
_pipe@9 = oaspec@internal@util@string_extra:indent(
_pipe@8,
3,
<<<<"case "/utf8, Decode_fn/binary>>/binary,
" {"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@9,
4,
<<"Ok(decoded_body) -> {"/utf8>>
);
_ ->
Decode_fn@1 = <<<<"decode.decode_"/utf8,
(oaspec@internal@util@naming:to_snake_case(
Op_id
))/binary>>/binary,
"_request_body(body)"/utf8>>,
_pipe@10 = Sb@14,
_pipe@11 = oaspec@internal@util@string_extra:indent(
_pipe@10,
3,
<<<<"case "/utf8, Decode_fn@1/binary>>/binary,
" {"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@11,
4,
<<"Ok(decoded_body) -> {"/utf8>>
)
end;
_ ->
Sb@14
end;
{_, _} ->
Sb@14
end,
Sb@16 = case {Needs_guard_validation, Body_schema_ref_name} of
{true, {some, Name@3}} ->
Validate_fn = <<<<"guards.validate_"/utf8,
(oaspec@internal@util@naming:to_snake_case(Name@3))/binary>>/binary,
"(decoded_body)"/utf8>>,
_pipe@12 = Sb@15,
_pipe@13 = oaspec@internal@util@string_extra:indent(
_pipe@12,
3,
<<<<"case "/utf8, Validate_fn/binary>>/binary, " {"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@13,
4,
<<"Ok(decoded_body) -> {"/utf8>>
);
{_, _} ->
Sb@15
end,
Sb@17 = case erlang:element(7, Operation) of
{some, {value, Rb@3}} ->
case oaspec@internal@codegen@server_request_decode:request_body_uses_form_urlencoded(
Rb@3
) of
true ->
_pipe@14 = Sb@16,
oaspec@internal@util@string_extra:indent(
_pipe@14,
3,
<<"let form_body = parse_form_body(body)"/utf8>>
);
false ->
case oaspec@internal@codegen@server_request_decode:request_body_uses_multipart(
Rb@3
) of
true ->
_pipe@15 = Sb@16,
oaspec@internal@util@string_extra:indent(
_pipe@15,
3,
<<"let multipart_body = parse_multipart_body(body, headers)"/utf8>>
);
false ->
Sb@16
end
end;
_ ->
Sb@16
end,
Sb@18 = begin
_pipe@16 = Sb@17,
oaspec@internal@util@string_extra:indent(
_pipe@16,
3,
<<<<"let request = request_types."/utf8, Request_type_name/binary>>/binary,
"("/utf8>>
)
end,
Sb@20 = gleam@list:fold(
Params_with_field_names,
Sb@18,
fun(Sb@19, Entry@1) ->
{Param, Field_name} = Entry@1,
Trailing = <<","/utf8>>,
Value_expr = case erlang:element(3, Param) of
in_path ->
case oaspec@internal@codegen@server_request_decode:param_needs_result_unwrap(
Param
) of
true ->
<<(oaspec@internal@util@naming:to_snake_case(
erlang:element(2, Param)
))/binary,
"_parsed"/utf8>>;
false ->
Var_name@1 = oaspec@internal@util@naming:to_snake_case(
erlang:element(2, Param)
),
oaspec@internal@codegen@server_request_decode:param_parse_expr(
Var_name@1,
Param
)
end;
in_query ->
Key@1 = erlang:element(2, Param),
Raw_var@3 = <<(oaspec@internal@util@naming:to_snake_case(
erlang:element(2, Param)
))/binary,
"_raw"/utf8>>,
case {oaspec@internal@codegen@server_request_decode:is_deep_object_param(
Param,
Ctx
),
erlang:element(5, Param)} of
{true, true} ->
oaspec@internal@codegen@server_request_decode:deep_object_required_expr(
Key@1,
Param,
Op_id,
Ctx
);
{true, false} ->
oaspec@internal@codegen@server_request_decode:deep_object_optional_expr(
Key@1,
Param,
Op_id,
Ctx
);
{false, true} ->
oaspec@internal@codegen@server_request_decode:query_required_expr(
Raw_var@3,
Param,
Ctx
);
{false, false} ->
oaspec@internal@codegen@server_request_decode:query_optional_expr(
Key@1,
Param,
Ctx
)
end;
in_header ->
Key@2 = string:lowercase(erlang:element(2, Param)),
Raw_var@4 = <<(oaspec@internal@util@naming:to_snake_case(
erlang:element(2, Param)
))/binary,
"_raw"/utf8>>,
case erlang:element(5, Param) of
true ->
oaspec@internal@codegen@server_request_decode:header_required_expr(
Raw_var@4,
Param
);
false ->
oaspec@internal@codegen@server_request_decode:header_optional_expr(
Key@2,
Param
)
end;
in_cookie ->
Key@3 = erlang:element(2, Param),
Raw_var@5 = <<(oaspec@internal@util@naming:to_snake_case(
erlang:element(2, Param)
))/binary,
"_raw"/utf8>>,
case erlang:element(5, Param) of
true ->
oaspec@internal@codegen@server_request_decode:cookie_required_expr(
Raw_var@5,
Param
);
false ->
oaspec@internal@codegen@server_request_decode:cookie_optional_expr(
Key@3,
Param
)
end
end,
_pipe@17 = Sb@19,
oaspec@internal@util@string_extra:indent(
_pipe@17,
4,
<<<<<<Field_name/binary, ": "/utf8>>/binary, Value_expr/binary>>/binary,
Trailing/binary>>
)
end
),
Sb@21 = case Needs_body_guard of
true ->
_pipe@18 = Sb@20,
oaspec@internal@util@string_extra:indent(
_pipe@18,
4,
<<"body: decoded_body,"/utf8>>
);
false ->
case erlang:element(7, Operation) of
{some, {value, Rb@4}} ->
Body_expr = oaspec@internal@codegen@server_request_decode:generate_body_decode_expr(
Rb@4,
Op_id,
Ctx
),
_pipe@19 = Sb@20,
oaspec@internal@util@string_extra:indent(
_pipe@19,
4,
<<<<"body: "/utf8, Body_expr/binary>>/binary, ","/utf8>>
);
_ ->
Sb@20
end
end,
Sb@22 = begin
_pipe@20 = Sb@21,
oaspec@internal@util@string_extra:indent(_pipe@20, 3, <<")"/utf8>>)
end,
Sb@23 = begin
_pipe@21 = Sb@22,
_pipe@22 = oaspec@internal@util@string_extra:indent(
_pipe@21,
3,
<<<<"let response = handlers_generated."/utf8, Fn_name/binary>>/binary,
"(app_state, request)"/utf8>>
),
generate_response_conversion(
_pipe@22,
Response_type_name,
Operation,
Ctx
)
end,
Sb@24 = case Needs_guard_validation of
true ->
_pipe@23 = Sb@23,
_pipe@24 = oaspec@internal@util@string_extra:indent(
_pipe@23,
4,
<<"}"/utf8>>
),
_pipe@25 = oaspec@internal@util@string_extra:indent(
_pipe@24,
4,
<<"Error(errors) -> ServerResponse(status: 422, body: TextBody(json.to_string(json.array(errors, guards.validation_failure_to_json))), headers: [#(\"content-type\", \"application/json\")])"/utf8>>
),
oaspec@internal@util@string_extra:indent(_pipe@25, 3, <<"}"/utf8>>);
false ->
Sb@23
end,
Sb@25 = case Needs_body_guard of
true ->
_pipe@26 = Sb@24,
_pipe@27 = oaspec@internal@util@string_extra:indent(
_pipe@26,
4,
<<"}"/utf8>>
),
_pipe@28 = oaspec@internal@util@string_extra:indent(
_pipe@27,
4,
<<"Error(_) -> "/utf8,
(problem_response_expr(400, <<"invalid request body"/utf8>>))/binary>>
),
oaspec@internal@util@string_extra:indent(_pipe@28, 3, <<"}"/utf8>>);
false ->
Sb@24
end,
Sb@27 = gleam@list:fold(
Required_cookie_params,
Sb@25,
fun(Sb@26, P@12) ->
close_single_value_required_parse_case(Sb@26, P@12, Ctx)
end
),
Sb@29 = gleam@list:fold(
Required_cookie_params,
Sb@27,
fun(Sb@28, _) -> close_lookup_case(Sb@28) end
),
Sb@31 = gleam@list:fold(
Required_header_params,
Sb@29,
fun(Sb@30, P@13) ->
close_single_value_required_parse_case(Sb@30, P@13, Ctx)
end
),
Sb@33 = gleam@list:fold(
Required_header_params,
Sb@31,
fun(Sb@32, _) -> close_lookup_case(Sb@32) end
),
Sb@35 = gleam@list:fold(
Required_query_params,
Sb@33,
fun(Sb@34, P@14) ->
close_query_required_parse_case(Sb@34, P@14, Ctx)
end
),
Sb@37 = gleam@list:fold(
Required_query_params,
Sb@35,
fun(Sb@36, _) -> close_lookup_case(Sb@36) end
),
gleam@list:fold(
Path_params_needing_parse,
Sb@37,
fun(Sb@38, _) -> _pipe@29 = Sb@38,
_pipe@30 = oaspec@internal@util@string_extra:indent(
_pipe@29,
4,
<<"}"/utf8>>
),
_pipe@31 = oaspec@internal@util@string_extra:indent(
_pipe@30,
4,
<<"Error(_) -> "/utf8,
(problem_response_expr(
400,
<<"invalid path parameter"/utf8>>
))/binary>>
),
oaspec@internal@util@string_extra:indent(_pipe@31, 3, <<"}"/utf8>>) end
).
-file("src/oaspec/internal/codegen/server.gleam", 379).
?DOC(false).
-spec generate_route_body(
gleam@string_tree:string_tree(),
binary(),
binary(),
oaspec@internal@openapi@spec:operation(oaspec@internal@openapi@spec:resolved()),
binary(),
boolean(),
oaspec@internal@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_route_body(Sb, Op_id, Fn_name, Operation, Path, Has_params, Ctx) ->
Type_name = oaspec@internal@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@internal@util@string_extra:indent(
_pipe,
3,
<<<<"let response = handlers_generated."/utf8, Fn_name/binary>>/binary,
"(app_state)"/utf8>>
),
generate_response_conversion(
_pipe@1,
Response_type_name,
Operation,
Ctx
);
true ->
Request_type_name = <<Type_name/binary, "Request"/utf8>>,
generate_safe_request_and_dispatch(
Sb,
Request_type_name,
Response_type_name,
Op_id,
Fn_name,
Operation,
Path,
Ctx
)
end.
-file("src/oaspec/internal/codegen/server.gleam", 1467).
?DOC(false).
-spec is_path_param(binary()) -> boolean().
is_path_param(Segment) ->
case Segment of
<<"{"/utf8, _/binary>> ->
true;
_ ->
false
end.
-file("src/oaspec/internal/codegen/server.gleam", 1475).
?DOC(false).
-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/internal/codegen/server.gleam", 1446).
?DOC(false).
-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@internal@util@naming:to_snake_case(Param_name);
false ->
<<<<"\""/utf8, Seg/binary>>/binary, "\""/utf8>>
end end),
<<<<"["/utf8,
(oaspec@internal@util@string_extra:join_with(
Patterns,
<<", "/utf8>>
))/binary>>/binary,
"]"/utf8>>.
-file("src/oaspec/internal/codegen/server.gleam", 240).
?DOC(false).
-spec generate_router(
oaspec@internal@codegen@context:context(),
list({binary(),
oaspec@internal@openapi@spec:operation(oaspec@internal@openapi@spec:resolved()),
binary(),
oaspec@internal@openapi@spec:http_method()})
) -> binary().
generate_router(Ctx, Operations) ->
Requirements = oaspec@internal@codegen@router_ir:analyze(Ctx),
All_imports = oaspec@internal@codegen@router_ir:imports(Requirements, Ctx),
Sb = begin
_pipe = oaspec@internal@util@string_extra:file_header(<<"0.48.0"/utf8>>),
oaspec@internal@util@string_extra:imports(_pipe, All_imports)
end,
Sb@1 = begin
_pipe@1 = Sb,
_pipe@2 = oaspec@internal@util@string_extra:doc_comment(
_pipe@1,
<<"Response body payload — text, raw bytes, or no body. The router
emits `BytesBody` for `application/octet-stream` (and other binary
content types) so adapters never have to round-trip bytes through a
String."/utf8>>
),
_pipe@3 = oaspec@internal@util@string_extra:line(
_pipe@2,
<<"pub type ResponseBody {"/utf8>>
),
_pipe@4 = oaspec@internal@util@string_extra:indent(
_pipe@3,
1,
<<"TextBody(String)"/utf8>>
),
_pipe@5 = oaspec@internal@util@string_extra:indent(
_pipe@4,
1,
<<"BytesBody(BitArray)"/utf8>>
),
_pipe@6 = oaspec@internal@util@string_extra:indent(
_pipe@5,
1,
<<"EmptyBody"/utf8>>
),
_pipe@7 = oaspec@internal@util@string_extra:line(_pipe@6, <<"}"/utf8>>),
_pipe@8 = oaspec@internal@util@string_extra:blank_line(_pipe@7),
_pipe@9 = oaspec@internal@util@string_extra:doc_comment(
_pipe@8,
<<"A server response with status code, body, and headers."/utf8>>
),
_pipe@10 = oaspec@internal@util@string_extra:line(
_pipe@9,
<<"pub type ServerResponse {"/utf8>>
),
_pipe@11 = oaspec@internal@util@string_extra:indent(
_pipe@10,
1,
<<"ServerResponse(status: Int, body: ResponseBody, headers: List(#(String, String)))"/utf8>>
),
_pipe@12 = oaspec@internal@util@string_extra:line(
_pipe@11,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:blank_line(_pipe@12)
end,
Sb@2 = case erlang:element(4, Requirements) of
true ->
oaspec@internal@util@string_extra:raw(
Sb@1,
<<"fn deep_object_present(query: Dict(String, List(String)), prefix: String, props: List(String)) -> Bool {
list.any(props, fn(prop) { dict.has_key(query, prefix <> \"[\" <> prop <> \"]\") })
}
"/utf8>>
);
false ->
Sb@1
end,
Sb@3 = case erlang:element(3, Requirements) of
true ->
oaspec@internal@util@string_extra:raw(
Sb@2,
<<"fn deep_object_present_any(query: Dict(String, List(String)), prefix: String) -> Bool {
let prefix_bracket = prefix <> \"[\"
dict.fold(query, False, fn(found, k, _v) { found || string.starts_with(k, prefix_bracket) })
}
fn deep_object_additional_properties(query: Dict(String, List(String)), prefix: String, known_props: List(String)) -> Dict(String, List(String)) {
let prefix_bracket = prefix <> \"[\"
let prefix_len = string.length(prefix_bracket)
dict.fold(query, dict.new(), fn(acc, k, v) {
case string.starts_with(k, prefix_bracket) && string.ends_with(k, \"]\") {
True -> {
let prop = string.slice(k, prefix_len, string.length(k) - prefix_len - 1)
case list.contains(known_props, prop) { True -> acc False -> dict.insert(acc, prop, v) }
}
False -> acc
}
})
}
"/utf8>>
);
false ->
Sb@2
end,
Sb@4 = case erlang:element(5, Requirements) of
true ->
oaspec@internal@util@string_extra:raw(
Sb@3,
<<"@external(erlang, \"gleam_stdlib\", \"identity\")
fn coerce_dict(value: Dict(String, List(String))) -> Dict(String, dynamic.Dynamic)
"/utf8>>
);
false ->
Sb@3
end,
Sb@5 = case erlang:element(6, Requirements) of
true ->
oaspec@internal@util@string_extra:raw(
Sb@4,
<<"fn form_url_decode(value: String) -> String {
let value = string.replace(value, \"+\", \" \")
case uri.percent_decode(value) { Ok(decoded) -> decoded Error(_) -> value }
}
fn parse_form_body(body: String) -> Dict(String, List(String)) {
let parts = case body { \"\" -> [] _ -> string.split(body, \"&\") }
list.fold(parts, dict.new(), fn(acc, part) {
case part {
\"\" -> acc
_ ->
case string.split_once(part, on: \"=\") {
Ok(#(raw_key, raw_value)) -> {
let key = form_url_decode(raw_key)
let value = form_url_decode(raw_value)
case dict.get(acc, key) {
Ok(existing) -> dict.insert(acc, key, list.append(existing, [value]))
Error(_) -> dict.insert(acc, key, [value])
}
}
Error(_) -> {
let key = form_url_decode(part)
case dict.get(acc, key) {
Ok(existing) -> dict.insert(acc, key, list.append(existing, [\"\"]))
Error(_) -> dict.insert(acc, key, [\"\"])
}
}
}
}
})
}
"/utf8>>
);
false ->
Sb@4
end,
Sb@6 = case erlang:element(7, Requirements) of
true ->
oaspec@internal@util@string_extra:raw(
Sb@5,
<<"fn multipart_boundary(headers: Dict(String, String)) -> Result(String, Nil) {
case dict.get(headers, \"content-type\") {
Ok(content_type) ->
list.find_map(string.split(content_type, \";\"), fn(part) {
let trimmed = string.trim(part)
case string.starts_with(trimmed, \"boundary=\") {
True -> Ok(string.replace(trimmed, \"boundary=\", \"\"))
False -> Error(Nil)
}
})
Error(_) -> Error(Nil)
}
}
fn multipart_name(raw_headers: String) -> Result(String, Nil) {
list.find_map(string.split(raw_headers, \"\\r\\n\"), fn(line) {
case string.contains(line, \"name=\") {
True ->
list.find_map(string.split(line, \";\"), fn(part) {
let trimmed = string.trim(part)
case string.starts_with(trimmed, \"name=\") {
True -> Ok(string.replace(string.replace(trimmed, \"name=\", \"\"), \"\\\"\", \"\"))
False -> Error(Nil)
}
})
False -> Error(Nil)
}
})
}
fn parse_multipart_body(body: String, headers: Dict(String, String)) -> Dict(String, List(String)) {
case multipart_boundary(headers) {
Ok(boundary) -> {
let delimiter = \"--\" <> boundary
let parts = string.split(body, delimiter)
list.fold(parts, dict.new(), fn(acc, part) {
let normalized_part = part |> string.remove_prefix(\"\\r\\n\") |> string.remove_suffix(\"\\r\\n\")
case normalized_part == \"\" || normalized_part == \"--\" {
True -> acc
False ->
case string.split_once(normalized_part, on: \"\\r\\n\\r\\n\") {
Ok(#(raw_part_headers, raw_value)) ->
case multipart_name(raw_part_headers) {
Ok(name) -> {
let value = raw_value
case dict.get(acc, name) {
Ok(existing) -> dict.insert(acc, name, list.append(existing, [value]))
Error(_) -> dict.insert(acc, name, [value])
}
}
Error(_) -> acc
}
Error(_) -> acc
}
}
})
}
Error(_) -> dict.new()
}
}
"/utf8>>
);
false ->
Sb@5
end,
Sb@7 = case erlang:element(8, Requirements) of
true ->
oaspec@internal@util@string_extra:raw(
Sb@6,
<<"fn form_object_present(form_body: Dict(String, List(String)), prefix: String, props: List(String)) -> Bool {
list.any(props, fn(prop) { dict.has_key(form_body, prefix <> \"[\" <> prop <> \"]\") })
}
"/utf8>>
);
false ->
Sb@6
end,
Sb@8 = begin
_pipe@13 = Sb@7,
_pipe@14 = oaspec@internal@util@string_extra:doc_comment(
_pipe@13,
<<"Route an incoming request to the appropriate handler."/utf8>>
),
_pipe@15 = oaspec@internal@util@string_extra:line(
_pipe@14,
<<<<<<<<<<<<"pub fn route(app_state: handlers.State, method: String, path: List(String), "/utf8,
(route_arg_name(
<<"query"/utf8>>,
erlang:element(21, Requirements)
))/binary>>/binary,
": Dict(String, List(String)), "/utf8>>/binary,
(route_arg_name(
<<"headers"/utf8>>,
erlang:element(22, Requirements)
))/binary>>/binary,
": Dict(String, String), "/utf8>>/binary,
(route_arg_name(
<<"body"/utf8>>,
erlang:element(23, Requirements)
))/binary>>/binary,
": String) -> ServerResponse {"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@15,
1,
<<"case method, path {"/utf8>>
)
end,
Sb@10 = gleam@list:fold(
Operations,
Sb@8,
fun(Sb@9, Op) ->
{Op_id, Operation, Path, Method} = Op,
Fn_name = oaspec@internal@util@naming:operation_to_function_name(
Op_id
),
Method_str = oaspec@internal@openapi@spec:method_to_string(Method),
Path_pattern = path_to_pattern(Path),
Has_params = not gleam@list:is_empty(erlang:element(6, Operation))
orelse gleam@option:is_some(erlang:element(7, Operation)),
_pipe@16 = Sb@9,
_pipe@17 = oaspec@internal@util@string_extra:indent(
_pipe@16,
2,
<<<<<<<<"\""/utf8, Method_str/binary>>/binary, "\", "/utf8>>/binary,
Path_pattern/binary>>/binary,
" -> {"/utf8>>
),
_pipe@18 = generate_route_body(
_pipe@17,
Op_id,
Fn_name,
Operation,
Path,
Has_params,
Ctx
),
oaspec@internal@util@string_extra:indent(_pipe@18, 2, <<"}"/utf8>>)
end
),
Sb@11 = begin
_pipe@19 = Sb@10,
_pipe@20 = oaspec@internal@util@string_extra:indent(
_pipe@19,
2,
<<"_, _ -> "/utf8,
(problem_response_expr(404, <<"not found"/utf8>>))/binary>>
),
_pipe@21 = oaspec@internal@util@string_extra:indent(
_pipe@20,
1,
<<"}"/utf8>>
),
_pipe@22 = oaspec@internal@util@string_extra:line(
_pipe@21,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:blank_line(_pipe@22)
end,
Sb@12 = case erlang:element(13, Requirements) of
true ->
generate_cookie_lookup(Sb@11);
false ->
Sb@11
end,
oaspec@internal@util@string_extra:to_string(Sb@12).
-file("src/oaspec/internal/codegen/server.gleam", 35).
?DOC(false).
-spec generate(oaspec@internal@codegen@context:context()) -> list(oaspec@internal@codegen@context:generated_file()).
generate(Ctx) ->
Operations = oaspec@internal@codegen@context:operations(Ctx),
Handlers_content = generate_handlers(Ctx, Operations),
Handlers_generated_content = generate_handlers_generated(Ctx, Operations),
Router_content = generate_router(Ctx, Operations),
[{generated_file,
<<"handlers.gleam"/utf8>>,
Handlers_content,
server_target,
skip_if_exists},
{generated_file,
<<"handlers_generated.gleam"/utf8>>,
Handlers_generated_content,
server_target,
overwrite},
{generated_file,
<<"router.gleam"/utf8>>,
Router_content,
server_target,
overwrite}].