-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.65.0"/utf8>>), oaspec@internal@util@string_extra:imports( _pipe, [<>, <>, <>] ) 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", 399). ?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", 404). ?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", 803). ?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", 883). ?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", 899). ?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", 820). ?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", 957). ?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", 1048). ?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", 916). ?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", 999). ?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", 1063). ?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", 1322). ?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", 1300). ?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", 1421). ?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>>); _ -> <<<>/binary, (gleam@string:join(Header_chunks, <<", "/utf8>>))/binary>> end end. -file("src/oaspec/internal/codegen/server.gleam", 1464). ?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", 1440). ?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", 1398). ?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", 1347). ?DOC(false). -spec emit_response_arm( gleam@string_tree:string_tree(), binary(), binary(), boolean(), boolean(), binary(), gleam@option:option(binary()), list(header_spec()), boolean() ) -> gleam@string_tree:string_tree(). emit_response_arm( Sb, Variant_name, Status_int, Has_data, Has_headers, Body_expr, Content_type_header, Header_specs, Is_default ) -> Pattern_args = case {Is_default, Has_data, Has_headers} of {false, true, true} -> <<"(data, hdrs)"/utf8>>; {false, true, false} -> <<"(data)"/utf8>>; {false, false, true} -> <<"(hdrs)"/utf8>>; {false, false, false} -> <<""/utf8>>; {true, true, true} -> <<"(status, data, hdrs)"/utf8>>; {true, true, false} -> <<"(status, data)"/utf8>>; {true, false, true} -> <<"(status, hdrs)"/utf8>>; {true, false, false} -> <<"(status)"/utf8>> end, Status_expr = case Is_default of true -> <<"status"/utf8>>; false -> Status_int 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_expr/binary>>/binary, ", body: "/utf8>>/binary, Body_expr/binary>>/binary, ", headers: "/utf8>>/binary, Headers_expr/binary>>/binary, ")"/utf8>> ). -file("src/oaspec/internal/codegen/server.gleam", 1474). ?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", 1077). ?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 = <>, Status_int = oaspec@internal@util@http:status_code_to_int( Status_code ), Is_default = case Status_code of default_status -> true; _ -> false end, 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, Is_default ); [{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, Is_default ); none -> emit_response_arm( Sb@2, Variant_name, Status_int, false, Has_headers, <<"EmptyBody"/utf8>>, none, Header_specs, Is_default ) 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, Is_default ); none -> emit_response_arm( Sb@2, Variant_name, Status_int, false, Has_headers, <<"EmptyBody"/utf8>>, none, Header_specs, Is_default ) 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, Is_default ); none -> emit_response_arm( Sb@2, Variant_name, Status_int, false, Has_headers, <<"EmptyBody"/utf8>>, none, Header_specs, Is_default ) 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, Is_default ); none -> emit_response_arm( Sb@2, Variant_name, Status_int, false, Has_headers, <<"EmptyBody"/utf8>>, none, Header_specs, Is_default ) 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, Is_default ); none -> emit_response_arm( Sb@2, Variant_name, Status_int, false, Has_headers, <<"EmptyBody"/utf8>>, none, Header_specs, Is_default ) end; wildcard -> 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, Is_default ); none -> emit_response_arm( Sb@2, Variant_name, Status_int, false, Has_headers, <<"EmptyBody"/utf8>>, none, Header_specs, Is_default ) 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, Is_default ); none -> emit_response_arm( Sb@2, Variant_name, Status_int, false, Has_headers, <<"EmptyBody"/utf8>>, none, Header_specs, Is_default ) 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, Is_default ) 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", 454). ?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, < {"/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, <<<<<>/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", 411). ?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 = <>, 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 = <>, 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", 1536). ?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", 1544). ?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", 1515). ?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.65.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(10, 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(23, Requirements) ))/binary>>/binary, ": Dict(String, List(String)), "/utf8>>/binary, (route_arg_name( <<"headers"/utf8>>, erlang:element(24, Requirements) ))/binary>>/binary, ": Dict(String, String), "/utf8>>/binary, (route_arg_name( <<"body"/utf8>>, erlang:element(25, Requirements) ))/binary>>/binary, (case erlang:element(8, Requirements) of true -> <<": BitArray) -> ServerResponse {"/utf8>>; false -> <<": String) -> ServerResponse {"/utf8>> end)/binary>> ), 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)), Arm_sb = begin _pipe@16 = Sb@9, oaspec@internal@util@string_extra:indent( _pipe@16, 2, <<<<<<<<"\""/utf8, Method_str/binary>>/binary, "\", "/utf8>>/binary, Path_pattern/binary>>/binary, " -> {"/utf8>> ) end, Arm_sb@1 = case {erlang:element(8, Requirements), gleam@option:is_some(erlang:element(7, Operation)), oaspec@internal@codegen@server_request_decode:operation_uses_octet_stream_body( Operation )} of {true, true, false} -> _pipe@17 = Arm_sb, oaspec@internal@util@string_extra:indent( _pipe@17, 3, <<"let body = bit_array.to_string(body) |> result.unwrap(\"\")"/utf8>> ); {_, _, _} -> Arm_sb end, _pipe@18 = Arm_sb@1, _pipe@19 = generate_route_body( _pipe@18, Op_id, Fn_name, Operation, Path, Has_params, Ctx ), oaspec@internal@util@string_extra:indent(_pipe@19, 2, <<"}"/utf8>>) end ), Sb@11 = begin _pipe@20 = Sb@10, _pipe@21 = oaspec@internal@util@string_extra:indent( _pipe@20, 2, <<"_, _ -> "/utf8, (problem_response_expr(404, <<"not found"/utf8>>))/binary>> ), _pipe@22 = oaspec@internal@util@string_extra:indent( _pipe@21, 1, <<"}"/utf8>> ), _pipe@23 = oaspec@internal@util@string_extra:line( _pipe@22, <<"}"/utf8>> ), oaspec@internal@util@string_extra:blank_line(_pipe@23) end, Sb@12 = case erlang:element(15, 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}].