-module(oaspec@codegen@server). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/oaspec/codegen/server.gleam"). -export([generate/1]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. -file("src/oaspec/codegen/server.gleam", 62). ?DOC(" Generate a single handler stub.\n"). -spec generate_handler( gleam@string_tree:string_tree(), binary(), oaspec@openapi@spec:operation(oaspec@openapi@spec:resolved()), oaspec@codegen@context:context() ) -> gleam@string_tree:string_tree(). generate_handler(Sb, Op_id, Operation, _) -> Fn_name = oaspec@util@naming:operation_to_function_name(Op_id), Request_type = <<(oaspec@util@naming:schema_to_type_name(Op_id))/binary, "Request"/utf8>>, Response_type = <<(oaspec@util@naming:schema_to_type_name(Op_id))/binary, "Response"/utf8>>, Sb@1 = case erlang:element(3, Operation) of {some, Summary} -> _pipe = Sb, oaspec@util@string_extra:doc_comment(_pipe, Summary); _ -> Sb end, Sb@2 = case erlang:element(4, Operation) of {some, Desc} -> _pipe@1 = Sb@1, oaspec@util@string_extra:doc_comment(_pipe@1, Desc); _ -> Sb@1 end, Has_params = not gleam@list:is_empty(erlang:element(6, Operation)) orelse gleam@option:is_some( erlang:element(7, Operation) ), Sb@3 = case Has_params of true -> _pipe@2 = Sb@2, oaspec@util@string_extra:line( _pipe@2, <<<<<<<<<<<<"pub fn "/utf8, Fn_name/binary>>/binary, "(req: request_types."/utf8>>/binary, Request_type/binary>>/binary, ") -> response_types."/utf8>>/binary, Response_type/binary>>/binary, " {"/utf8>> ); false -> _pipe@3 = Sb@2, oaspec@util@string_extra:line( _pipe@3, <<<<<<<<"pub fn "/utf8, Fn_name/binary>>/binary, "() -> response_types."/utf8>>/binary, Response_type/binary>>/binary, " {"/utf8>> ) end, Sb@4 = case Has_params of true -> _pipe@4 = Sb@3, oaspec@util@string_extra:indent(_pipe@4, 1, <<"let _ = req"/utf8>>); false -> Sb@3 end, _pipe@5 = Sb@4, _pipe@6 = oaspec@util@string_extra:indent( _pipe@5, 1, <<<<"panic as \"unimplemented: "/utf8, Fn_name/binary>>/binary, "\""/utf8>> ), _pipe@7 = oaspec@util@string_extra:line(_pipe@6, <<"}"/utf8>>), oaspec@util@string_extra:blank_line(_pipe@7). -file("src/oaspec/codegen/server.gleam", 147). ?DOC(" Extract a short suffix from a URL expression for function naming.\n"). -spec url_expression_to_suffix(binary()) -> binary(). url_expression_to_suffix(Url_expression) -> Parts = gleam@string:split(Url_expression, <<"/"/utf8>>), case gleam@list:last(Parts) of {ok, Last} -> _pipe = Last, _pipe@1 = gleam@string:replace(_pipe, <<"{"/utf8>>, <<""/utf8>>), _pipe@2 = gleam@string:replace(_pipe@1, <<"}"/utf8>>, <<""/utf8>>), _pipe@3 = gleam@string:replace(_pipe@2, <<"$"/utf8>>, <<""/utf8>>), gleam@string:replace(_pipe@3, <<"#"/utf8>>, <<""/utf8>>); {error, _} -> <<"handler"/utf8>> end. -file("src/oaspec/codegen/server.gleam", 116). ?DOC(" Generate callback handler stubs for an operation's callbacks.\n"). -spec generate_callback_handlers( gleam@string_tree:string_tree(), binary(), oaspec@openapi@spec:operation(oaspec@openapi@spec:resolved()) ) -> gleam@string_tree:string_tree(). generate_callback_handlers(Sb, Op_id, Operation) -> Callbacks = oaspec@codegen@ir_build:sorted_entries( erlang:element(11, Operation) ), gleam@list:fold( Callbacks, Sb, fun(Sb@1, Entry) -> {Callback_name, Callback} = Entry, Callback_entries = oaspec@codegen@ir_build:sorted_entries( erlang:element(2, Callback) ), gleam@list:fold( Callback_entries, Sb@1, fun(Sb@2, Cb_entry) -> {Url_expression, _} = Cb_entry, Fn_name = <<<<<<<<(oaspec@util@naming:operation_to_function_name( Op_id ))/binary, "_callback_"/utf8>>/binary, (oaspec@util@naming:to_snake_case(Callback_name))/binary>>/binary, "_"/utf8>>/binary, (oaspec@util@naming:to_snake_case( url_expression_to_suffix(Url_expression) ))/binary>>, _pipe = Sb@2, _pipe@1 = oaspec@util@string_extra:doc_comment( _pipe, <<<<<<"Callback handler stub for "/utf8, Callback_name/binary>>/binary, " on "/utf8>>/binary, Op_id/binary>> ), _pipe@2 = oaspec@util@string_extra:doc_comment( _pipe@1, <<"URL: "/utf8, Url_expression/binary>> ), _pipe@3 = oaspec@util@string_extra:line( _pipe@2, <<<<"pub fn "/utf8, Fn_name/binary>>/binary, "() -> String {"/utf8>> ), _pipe@4 = oaspec@util@string_extra:indent( _pipe@3, 1, <<<<"panic as \"unimplemented: "/utf8, Fn_name/binary>>/binary, "\""/utf8>> ), _pipe@5 = oaspec@util@string_extra:line( _pipe@4, <<"}"/utf8>> ), oaspec@util@string_extra:blank_line(_pipe@5) end ) end ). -file("src/oaspec/codegen/server.gleam", 35). ?DOC(" Generate handler stubs for all operations.\n"). -spec generate_handlers(oaspec@codegen@context:context()) -> binary(). generate_handlers(Ctx) -> Sb = begin _pipe = oaspec@util@string_extra:file_header(<<"0.10.0"/utf8>>), oaspec@util@string_extra:imports( _pipe, [<<(erlang:element(5, erlang:element(3, Ctx)))/binary, "/request_types"/utf8>>, <<(erlang:element(5, erlang:element(3, Ctx)))/binary, "/response_types"/utf8>>] ) end, Operations = oaspec@openapi@operations:collect_operations(Ctx), Sb@2 = gleam@list:fold( Operations, Sb, fun(Sb@1, Op) -> {Op_id, Operation, _, _} = Op, generate_handler(Sb@1, Op_id, Operation, Ctx) end ), Sb@4 = gleam@list:fold( Operations, Sb@2, fun(Sb@3, Op@1) -> {Op_id@1, Operation@1, _, _} = Op@1, generate_callback_handlers(Sb@3, Op_id@1, Operation@1) end ), oaspec@util@string_extra:to_string(Sb@4). -file("src/oaspec/codegen/server.gleam", 735). -spec route_arg_name(binary(), boolean()) -> binary(). route_arg_name(Name, Used) -> case Used of true -> Name; false -> <<"_"/utf8, Name/binary>> end. -file("src/oaspec/codegen/server.gleam", 742). -spec generate_cookie_lookup(gleam@string_tree:string_tree()) -> gleam@string_tree:string_tree(). generate_cookie_lookup(Sb) -> _pipe = Sb, _pipe@1 = oaspec@util@string_extra:doc_comment( _pipe, <<"Extract a cookie value from the Cookie header."/utf8>> ), _pipe@2 = oaspec@util@string_extra:line( _pipe@1, <<"fn cookie_lookup(headers: Dict(String, String), key: String) -> Result(String, Nil) {"/utf8>> ), _pipe@3 = oaspec@util@string_extra:indent( _pipe@2, 1, <<"case dict.get(headers, \"cookie\") {"/utf8>> ), _pipe@4 = oaspec@util@string_extra:indent(_pipe@3, 2, <<"Ok(raw) ->"/utf8>>), _pipe@5 = oaspec@util@string_extra:indent( _pipe@4, 3, <<"list.find_map(string.split(raw, \";\"), fn(part) {"/utf8>> ), _pipe@6 = oaspec@util@string_extra:indent( _pipe@5, 4, <<"let trimmed = string.trim(part)"/utf8>> ), _pipe@7 = oaspec@util@string_extra:indent( _pipe@6, 4, <<"case string.split_once(trimmed, on: \"=\") {"/utf8>> ), _pipe@8 = oaspec@util@string_extra:indent( _pipe@7, 5, <<"Ok(#(cookie_key, cookie_value)) ->"/utf8>> ), _pipe@9 = oaspec@util@string_extra:indent( _pipe@8, 6, <<"case string.trim(cookie_key) == key {"/utf8>> ), _pipe@10 = oaspec@util@string_extra:indent( _pipe@9, 7, <<"True -> uri.percent_decode(string.trim(cookie_value))"/utf8>> ), _pipe@11 = oaspec@util@string_extra:indent( _pipe@10, 7, <<"False -> Error(Nil)"/utf8>> ), _pipe@12 = oaspec@util@string_extra:indent(_pipe@11, 6, <<"}"/utf8>>), _pipe@13 = oaspec@util@string_extra:indent( _pipe@12, 5, <<"Error(_) -> Error(Nil)"/utf8>> ), _pipe@14 = oaspec@util@string_extra:indent(_pipe@13, 4, <<"}"/utf8>>), _pipe@15 = oaspec@util@string_extra:indent(_pipe@14, 3, <<"})"/utf8>>), _pipe@16 = oaspec@util@string_extra:indent( _pipe@15, 2, <<"Error(_) -> Error(Nil)"/utf8>> ), _pipe@17 = oaspec@util@string_extra:indent(_pipe@16, 1, <<"}"/utf8>>), _pipe@18 = oaspec@util@string_extra:line(_pipe@17, <<"}"/utf8>>), oaspec@util@string_extra:blank_line(_pipe@18). -file("src/oaspec/codegen/server.gleam", 807). ?DOC(" Generate code to construct a typed request from raw inputs.\n"). -spec generate_request_construction( gleam@string_tree:string_tree(), binary(), binary(), oaspec@openapi@spec:operation(oaspec@openapi@spec:resolved()), binary(), oaspec@codegen@context:context() ) -> gleam@string_tree:string_tree(). generate_request_construction(Sb, Request_type_name, Op_id, Operation, _, Ctx) -> Sb@1 = case erlang:element(7, Operation) of {some, {value, Rb}} -> case oaspec@codegen@server_request_decode:request_body_uses_form_urlencoded( Rb ) of true -> _pipe = Sb, oaspec@util@string_extra:indent( _pipe, 3, <<"let form_body = parse_form_body(body)"/utf8>> ); false -> case oaspec@codegen@server_request_decode:request_body_uses_multipart( Rb ) of true -> _pipe@1 = Sb, oaspec@util@string_extra:indent( _pipe@1, 3, <<"let multipart_body = parse_multipart_body(body, headers)"/utf8>> ); false -> Sb end end; _ -> Sb end, Sb@2 = begin _pipe@2 = Sb@1, oaspec@util@string_extra:indent( _pipe@2, 3, <<<<"let request = request_types."/utf8, Request_type_name/binary>>/binary, "("/utf8>> ) end, Sb@4 = gleam@list:index_fold( gleam@list:filter_map(erlang:element(6, Operation), fun(R) -> case R of {value, P} -> {ok, P}; _ -> {error, nil} end end), Sb@2, fun(Sb@3, Param, _) -> Field_name = oaspec@util@naming:to_snake_case( erlang:element(2, Param) ), Trailing = <<","/utf8>>, Value_expr = case erlang:element(3, Param) of in_path -> Var_name = oaspec@util@naming:to_snake_case( erlang:element(2, Param) ), oaspec@codegen@server_request_decode:param_parse_expr( Var_name, Param ); in_query -> Key = erlang:element(2, Param), case {oaspec@codegen@server_request_decode:is_deep_object_param( Param, Ctx ), erlang:element(5, Param)} of {true, true} -> oaspec@codegen@server_request_decode:deep_object_required_expr( Key, Param, Op_id, Ctx ); {true, false} -> oaspec@codegen@server_request_decode:deep_object_optional_expr( Key, Param, Op_id, Ctx ); {false, true} -> oaspec@codegen@server_request_decode:query_required_expr( Key, Param ); {false, false} -> oaspec@codegen@server_request_decode:query_optional_expr( Key, Param ) end; in_header -> Key@1 = string:lowercase(erlang:element(2, Param)), case erlang:element(5, Param) of true -> oaspec@codegen@server_request_decode:header_required_expr( Key@1, Param ); false -> oaspec@codegen@server_request_decode:header_optional_expr( Key@1, Param ) end; in_cookie -> Key@2 = erlang:element(2, Param), case erlang:element(5, Param) of true -> oaspec@codegen@server_request_decode:cookie_required_expr( Key@2, Param ); false -> oaspec@codegen@server_request_decode:cookie_optional_expr( Key@2, Param ) end end, _pipe@3 = Sb@3, oaspec@util@string_extra:indent( _pipe@3, 4, <<<<<>/binary, Value_expr/binary>>/binary, Trailing/binary>> ) end ), Sb@5 = case erlang:element(7, Operation) of {some, {value, Rb@1}} -> Body_expr = oaspec@codegen@server_request_decode:generate_body_decode_expr( Rb@1, Op_id, Ctx ), _pipe@4 = Sb@4, oaspec@util@string_extra:indent( _pipe@4, 4, <<<<"body: "/utf8, Body_expr/binary>>/binary, ","/utf8>> ); _ -> Sb@4 end, _pipe@5 = Sb@5, oaspec@util@string_extra:indent(_pipe@5, 3, <<")"/utf8>>). -file("src/oaspec/codegen/server.gleam", 1058). ?DOC(" Get the encode function name for a schema reference.\n"). -spec get_encode_function( gleam@option:option(oaspec@openapi@schema:schema_ref()), oaspec@codegen@context:context() ) -> binary(). get_encode_function(Schema_ref, _) -> case Schema_ref of {some, {reference, _, Name}} -> <<<<"encode.encode_"/utf8, (oaspec@util@naming:to_snake_case(Name))/binary>>/binary, "_json"/utf8>>; {some, {inline, {array_schema, _, Items, _, _, _}}} -> case Items of {reference, _, Name@1} -> <<<<"fn(items) { json.array(items, encode.encode_"/utf8, (oaspec@util@naming:to_snake_case(Name@1))/binary>>/binary, "_json) }"/utf8>>; _ -> <<"json.string"/utf8>> end; {some, {inline, {string_schema, _, _, _, _, _, _}}} -> <<"json.string"/utf8>>; {some, {inline, {integer_schema, _, _, _, _, _, _, _}}} -> <<"json.int"/utf8>>; {some, {inline, {number_schema, _, _, _, _, _, _, _}}} -> <<"json.float"/utf8>>; {some, {inline, {boolean_schema, _}}} -> <<"json.bool"/utf8>>; _ -> <<"json.string"/utf8>> end. -file("src/oaspec/codegen/server.gleam", 906). ?DOC(" Generate code to convert a handler response to ServerResponse.\n"). -spec generate_response_conversion( gleam@string_tree:string_tree(), binary(), oaspec@openapi@spec:operation(oaspec@openapi@spec:resolved()), oaspec@codegen@context:context() ) -> gleam@string_tree:string_tree(). generate_response_conversion(Sb, Response_type_name, Operation, Ctx) -> Responses = oaspec@util@http:sort_response_entries( maps:to_list(erlang:element(8, Operation)) ), case gleam@list:is_empty(Responses) of true -> _pipe = Sb, oaspec@util@string_extra:indent( _pipe, 3, <<"ServerResponse(status: 200, body: \"\", headers: [])"/utf8>> ); false -> Sb@1 = begin _pipe@1 = Sb, oaspec@util@string_extra:indent( _pipe@1, 3, <<"case response {"/utf8>> ) end, Sb@3 = gleam@list:fold( Responses, Sb@1, fun(Sb@2, Entry) -> {Status_code, Ref_or} = Entry, case Ref_or of {value, Response} -> Variant_name = <>, Status_int = oaspec@util@http:status_code_to_int( Status_code ), Content_entries = maps:to_list( erlang:element(3, Response) ), case Content_entries of [] -> _pipe@2 = Sb@2, oaspec@util@string_extra:indent( _pipe@2, 4, <<<<<<<<"response_types."/utf8, Variant_name/binary>>/binary, " -> ServerResponse(status: "/utf8>>/binary, Status_int/binary>>/binary, ", body: \"\", headers: [])"/utf8>> ); [{Media_type_name, Media_type}] -> case Media_type_name of <<"application/json"/utf8>> -> case erlang:element(2, Media_type) of {some, _} -> Encode_fn = get_encode_function( erlang:element( 2, Media_type ), Ctx ), _pipe@3 = Sb@2, oaspec@util@string_extra:indent( _pipe@3, 4, <<<<<<<<<<<<"response_types."/utf8, Variant_name/binary>>/binary, "(data) -> ServerResponse(status: "/utf8>>/binary, Status_int/binary>>/binary, ", body: json.to_string("/utf8>>/binary, Encode_fn/binary>>/binary, "(data)), headers: [#(\"content-type\", \"application/json\")])"/utf8>> ); none -> _pipe@4 = Sb@2, oaspec@util@string_extra:indent( _pipe@4, 4, <<<<<<<<"response_types."/utf8, Variant_name/binary>>/binary, " -> ServerResponse(status: "/utf8>>/binary, Status_int/binary>>/binary, ", body: \"\", headers: [])"/utf8>> ) end; <<"text/plain"/utf8>> -> case erlang:element(2, Media_type) of {some, _} -> _pipe@5 = Sb@2, oaspec@util@string_extra:indent( _pipe@5, 4, <<<<<<<<<<<<"response_types."/utf8, Variant_name/binary>>/binary, "(data) -> ServerResponse(status: "/utf8>>/binary, Status_int/binary>>/binary, ", body: data, headers: [#(\"content-type\", \""/utf8>>/binary, Media_type_name/binary>>/binary, "\")])"/utf8>> ); none -> _pipe@6 = Sb@2, oaspec@util@string_extra:indent( _pipe@6, 4, <<<<<<<<"response_types."/utf8, Variant_name/binary>>/binary, " -> ServerResponse(status: "/utf8>>/binary, Status_int/binary>>/binary, ", body: \"\", headers: [])"/utf8>> ) end; <<"application/xml"/utf8>> -> case erlang:element(2, Media_type) of {some, _} -> _pipe@5 = Sb@2, oaspec@util@string_extra:indent( _pipe@5, 4, <<<<<<<<<<<<"response_types."/utf8, Variant_name/binary>>/binary, "(data) -> ServerResponse(status: "/utf8>>/binary, Status_int/binary>>/binary, ", body: data, headers: [#(\"content-type\", \""/utf8>>/binary, Media_type_name/binary>>/binary, "\")])"/utf8>> ); none -> _pipe@6 = Sb@2, oaspec@util@string_extra:indent( _pipe@6, 4, <<<<<<<<"response_types."/utf8, Variant_name/binary>>/binary, " -> ServerResponse(status: "/utf8>>/binary, Status_int/binary>>/binary, ", body: \"\", headers: [])"/utf8>> ) end; <<"text/xml"/utf8>> -> case erlang:element(2, Media_type) of {some, _} -> _pipe@5 = Sb@2, oaspec@util@string_extra:indent( _pipe@5, 4, <<<<<<<<<<<<"response_types."/utf8, Variant_name/binary>>/binary, "(data) -> ServerResponse(status: "/utf8>>/binary, Status_int/binary>>/binary, ", body: data, headers: [#(\"content-type\", \""/utf8>>/binary, Media_type_name/binary>>/binary, "\")])"/utf8>> ); none -> _pipe@6 = Sb@2, oaspec@util@string_extra:indent( _pipe@6, 4, <<<<<<<<"response_types."/utf8, Variant_name/binary>>/binary, " -> ServerResponse(status: "/utf8>>/binary, Status_int/binary>>/binary, ", body: \"\", headers: [])"/utf8>> ) end; <<"application/octet-stream"/utf8>> -> case erlang:element(2, Media_type) of {some, _} -> _pipe@5 = Sb@2, oaspec@util@string_extra:indent( _pipe@5, 4, <<<<<<<<<<<<"response_types."/utf8, Variant_name/binary>>/binary, "(data) -> ServerResponse(status: "/utf8>>/binary, Status_int/binary>>/binary, ", body: data, headers: [#(\"content-type\", \""/utf8>>/binary, Media_type_name/binary>>/binary, "\")])"/utf8>> ); none -> _pipe@6 = Sb@2, oaspec@util@string_extra:indent( _pipe@6, 4, <<<<<<<<"response_types."/utf8, Variant_name/binary>>/binary, " -> ServerResponse(status: "/utf8>>/binary, Status_int/binary>>/binary, ", body: \"\", headers: [])"/utf8>> ) end; _ -> case erlang:element(2, Media_type) of {some, _} -> Encode_fn@1 = get_encode_function( erlang:element( 2, Media_type ), Ctx ), _pipe@7 = Sb@2, oaspec@util@string_extra:indent( _pipe@7, 4, <<<<<<<<<<<<<<<<"response_types."/utf8, Variant_name/binary>>/binary, "(data) -> ServerResponse(status: "/utf8>>/binary, Status_int/binary>>/binary, ", body: json.to_string("/utf8>>/binary, Encode_fn@1/binary>>/binary, "(data)), headers: [#(\"content-type\", \""/utf8>>/binary, Media_type_name/binary>>/binary, "\")])"/utf8>> ); none -> _pipe@8 = Sb@2, oaspec@util@string_extra:indent( _pipe@8, 4, <<<<<<<<"response_types."/utf8, Variant_name/binary>>/binary, " -> ServerResponse(status: "/utf8>>/binary, Status_int/binary>>/binary, ", body: \"\", headers: [])"/utf8>> ) end end; [{First_media_type, _}, _ | _] -> _pipe@9 = Sb@2, oaspec@util@string_extra:indent( _pipe@9, 4, <<<<<<<<<<<<"response_types."/utf8, Variant_name/binary>>/binary, "(data) -> ServerResponse(status: "/utf8>>/binary, Status_int/binary>>/binary, ", body: data, headers: [#(\"content-type\", \""/utf8>>/binary, First_media_type/binary>>/binary, "\")])"/utf8>> ) end; _ -> Sb@2 end end ), _pipe@10 = Sb@3, oaspec@util@string_extra:indent(_pipe@10, 3, <<"}"/utf8>>) end. -file("src/oaspec/codegen/server.gleam", 768). ?DOC(" Generate the body of a single route case branch.\n"). -spec generate_route_body( gleam@string_tree:string_tree(), binary(), binary(), oaspec@openapi@spec:operation(oaspec@openapi@spec:resolved()), binary(), boolean(), oaspec@codegen@context:context() ) -> gleam@string_tree:string_tree(). generate_route_body(Sb, Op_id, Fn_name, Operation, Path, Has_params, Ctx) -> Type_name = oaspec@util@naming:schema_to_type_name(Op_id), Response_type_name = <>, case Has_params of false -> _pipe = Sb, _pipe@1 = oaspec@util@string_extra:indent( _pipe, 3, <<<<"let response = handlers."/utf8, Fn_name/binary>>/binary, "()"/utf8>> ), generate_response_conversion( _pipe@1, Response_type_name, Operation, Ctx ); true -> Request_type_name = <>, Sb@1 = generate_request_construction( Sb, Request_type_name, Op_id, Operation, Path, Ctx ), _pipe@2 = Sb@1, _pipe@3 = oaspec@util@string_extra:indent( _pipe@2, 3, <<<<"let response = handlers."/utf8, Fn_name/binary>>/binary, "(request)"/utf8>> ), generate_response_conversion( _pipe@3, Response_type_name, Operation, Ctx ) end. -file("src/oaspec/codegen/server.gleam", 1105). ?DOC(" Check if a path segment is a parameter.\n"). -spec is_path_param(binary()) -> boolean(). is_path_param(Segment) -> case Segment of <<"{"/utf8, _/binary>> -> true; _ -> false end. -file("src/oaspec/codegen/server.gleam", 1113). ?DOC(" Extract parameter name from {name}.\n"). -spec extract_param_name(binary()) -> binary(). extract_param_name(Segment) -> _pipe = Segment, _pipe@1 = gleam@string:replace(_pipe, <<"{"/utf8>>, <<""/utf8>>), gleam@string:replace(_pipe@1, <<"}"/utf8>>, <<""/utf8>>). -file("src/oaspec/codegen/server.gleam", 1084). ?DOC(" Convert an OpenAPI path to a Gleam pattern match expression.\n"). -spec path_to_pattern(binary()) -> binary(). path_to_pattern(Path) -> Segments = begin _pipe = Path, _pipe@1 = gleam@string:split(_pipe, <<"/"/utf8>>), gleam@list:filter(_pipe@1, fun(S) -> S /= <<""/utf8>> end) end, Patterns = gleam@list:map(Segments, fun(Seg) -> case is_path_param(Seg) of true -> Param_name = extract_param_name(Seg), oaspec@util@naming:to_snake_case(Param_name); false -> <<<<"\""/utf8, Seg/binary>>/binary, "\""/utf8>> end end), <<<<"["/utf8, (oaspec@util@string_extra:join_with(Patterns, <<", "/utf8>>))/binary>>/binary, "]"/utf8>>. -file("src/oaspec/codegen/server.gleam", 162). ?DOC(" Generate a router module that dispatches requests.\n"). -spec generate_router(oaspec@codegen@context:context()) -> binary(). generate_router(Ctx) -> Operations = oaspec@openapi@operations:collect_operations(Ctx), Has_deep_object = gleam@list:any( Operations, fun(Op) -> {_, Operation, _, _} = Op, gleam@list:any( erlang:element(6, Operation), fun(Ref_p) -> case Ref_p of {value, P} -> oaspec@codegen@server_request_decode:is_deep_object_param( P, Ctx ); _ -> false end end ) end ), Has_form_urlencoded_body = gleam@list:any( Operations, fun(Op@1) -> {_, Operation@1, _, _} = Op@1, oaspec@codegen@server_request_decode:operation_uses_form_urlencoded_body( Operation@1 ) end ), Has_multipart_body = gleam@list:any( Operations, fun(Op@2) -> {_, Operation@2, _, _} = Op@2, oaspec@codegen@server_request_decode:operation_uses_multipart_body( Operation@2 ) end ), Has_nested_form_urlencoded_body = gleam@list:any( Operations, fun(Op@3) -> {_, Operation@3, _, _} = Op@3, case erlang:element(7, Operation@3) of {some, {value, Rb}} -> oaspec@codegen@server_request_decode:form_urlencoded_body_has_nested_object( Rb, Ctx ); _ -> false end end ), Needs_dict = gleam@list:any( Operations, fun(Op@4) -> {_, Operation@4, _, _} = Op@4, Has_query = gleam@list:any( erlang:element(6, Operation@4), fun(Ref_p@1) -> case Ref_p@1 of {value, P@1} -> erlang:element(3, P@1) =:= in_query; _ -> false end end ), Has_header = gleam@list:any( erlang:element(6, Operation@4), fun(Ref_p@2) -> case Ref_p@2 of {value, P@2} -> erlang:element(3, P@2) =:= in_header; _ -> false end end ), Has_query orelse Has_header end ), Needs_int = gleam@list:any( Operations, fun(Op@5) -> {_, Operation@5, _, _} = Op@5, (gleam@list:any( erlang:element(6, Operation@5), fun(Ref_p@3) -> case Ref_p@3 of {value, P@3} -> oaspec@codegen@server_request_decode:query_schema_needs_int( oaspec@openapi@spec:parameter_schema(P@3) ) orelse oaspec@codegen@server_request_decode:deep_object_param_needs_int( P@3, Ctx ); _ -> false end end ) orelse case erlang:element(7, Operation@5) of {some, {value, Rb@1}} -> oaspec@codegen@server_request_decode:form_urlencoded_body_needs_int( Rb@1, Ctx ); _ -> false end) orelse case erlang:element(7, Operation@5) of {some, {value, Rb@2}} -> oaspec@codegen@server_request_decode:multipart_body_needs_int( Rb@2, Ctx ); _ -> false end end ), Needs_float = gleam@list:any( Operations, fun(Op@6) -> {_, Operation@6, _, _} = Op@6, (gleam@list:any( erlang:element(6, Operation@6), fun(Ref_p@4) -> case Ref_p@4 of {value, P@4} -> oaspec@codegen@server_request_decode:query_schema_needs_float( oaspec@openapi@spec:parameter_schema(P@4) ) orelse oaspec@codegen@server_request_decode:deep_object_param_needs_float( P@4, Ctx ); _ -> false end end ) orelse case erlang:element(7, Operation@6) of {some, {value, Rb@3}} -> oaspec@codegen@server_request_decode:form_urlencoded_body_needs_float( Rb@3, Ctx ); _ -> false end) orelse case erlang:element(7, Operation@6) of {some, {value, Rb@4}} -> oaspec@codegen@server_request_decode:multipart_body_needs_float( Rb@4, Ctx ); _ -> false end end ), Needs_string = (Has_form_urlencoded_body orelse Has_multipart_body) orelse gleam@list:any( Operations, fun(Op@7) -> {_, Operation@7, _, _} = Op@7, gleam@list:any( erlang:element(6, Operation@7), fun(Ref_p@5) -> case Ref_p@5 of {value, P@5} -> case erlang:element(3, P@5) of in_cookie -> true; in_query -> oaspec@codegen@server_request_decode:query_schema_needs_string( oaspec@openapi@spec:parameter_schema( P@5 ) ) orelse oaspec@codegen@server_request_decode:deep_object_param_needs_string( P@5, Ctx ); in_header -> oaspec@codegen@server_request_decode:query_schema_needs_string( oaspec@openapi@spec:parameter_schema( P@5 ) ) orelse oaspec@codegen@server_request_decode:deep_object_param_needs_string( P@5, Ctx ); in_path -> oaspec@codegen@server_request_decode:query_schema_needs_string( oaspec@openapi@spec:parameter_schema( P@5 ) ) end; _ -> false end end ) orelse case erlang:element(7, Operation@7) of {some, {value, Rb@5}} -> oaspec@codegen@server_request_decode:form_urlencoded_body_needs_string( Rb@5, Ctx ); _ -> false end end ), Needs_cookie_lookup = gleam@list:any( Operations, fun(Op@8) -> {_, Operation@8, _, _} = Op@8, gleam@list:any( erlang:element(6, Operation@8), fun(Ref_p@6) -> case Ref_p@6 of {value, P@6} -> erlang:element(3, P@6) =:= in_cookie; _ -> false end end ) end ), Needs_list_import = (((Needs_cookie_lookup orelse Has_deep_object) orelse Has_form_urlencoded_body) orelse Has_multipart_body) orelse gleam@list:any( Operations, fun(Op@9) -> {_, Operation@9, _, _} = Op@9, gleam@list:any( erlang:element(6, Operation@9), fun(Ref_p@7) -> case Ref_p@7 of {value, P@7} -> case {erlang:element(3, P@7), oaspec@openapi@spec:parameter_schema(P@7)} of {in_query, {some, {inline, {array_schema, _, _, _, _, _}}}} -> true; {in_header, {some, {inline, {array_schema, _, _, _, _, _}}}} -> true; {_, _} -> false end; _ -> false end end ) end ), Needs_uri_import = Needs_cookie_lookup orelse Has_form_urlencoded_body, Needs_option = gleam@list:any( Operations, fun(Op@10) -> {_, Operation@10, _, _} = Op@10, Has_optional_params = gleam@list:any( erlang:element(6, Operation@10), fun(Ref_p@8) -> case Ref_p@8 of {value, P@8} -> not erlang:element(5, P@8); _ -> false end end ), Has_optional_deep_object_fields = gleam@list:any( erlang:element(6, Operation@10), fun(Ref_p@9) -> case Ref_p@9 of {value, P@9} -> oaspec@codegen@server_request_decode:deep_object_param_has_optional_fields( P@9, Ctx ); _ -> false end end ), Has_optional_form_urlencoded_fields = case erlang:element( 7, Operation@10 ) of {some, {value, Rb@6}} -> oaspec@codegen@server_request_decode:form_urlencoded_body_has_optional_fields( Rb@6, Ctx ); _ -> false end, Has_optional_multipart_fields = case erlang:element(7, Operation@10) of {some, {value, Rb@7}} -> oaspec@codegen@server_request_decode:multipart_body_has_optional_fields( Rb@7, Ctx ); _ -> false end, Has_optional_body = case erlang:element(7, Operation@10) of {some, {value, Rb@8}} -> not erlang:element(4, Rb@8); _ -> false end, (((Has_optional_params orelse Has_optional_deep_object_fields) orelse Has_optional_form_urlencoded_fields) orelse Has_optional_multipart_fields) orelse Has_optional_body end ), Needs_json = gleam@list:any( Operations, fun(Op@11) -> {_, Operation@11, _, _} = Op@11, Responses = maps:to_list(erlang:element(8, Operation@11)), gleam@list:any( Responses, fun(Entry) -> {_, Ref_or} = Entry, case Ref_or of {value, Response} -> Content_entries = maps:to_list( erlang:element(3, Response) ), case Content_entries of [{Media_type_name, Media_type}] -> case Media_type_name of <<"application/json"/utf8>> -> case erlang:element(2, Media_type) of {some, _} -> true; none -> false end; _ -> false end; _ -> false end; _ -> false end end ) end ), Needs_decode = Needs_json andalso gleam@list:any( Operations, fun(Op@12) -> {_, Operation@12, _, _} = Op@12, gleam@option:is_some(erlang:element(7, Operation@12)) end ), Needs_encode = Needs_json, Uses_query = gleam@list:any( Operations, fun(Op@13) -> {_, Operation@13, _, _} = Op@13, gleam@list:any( erlang:element(6, Operation@13), fun(Ref_p@10) -> case Ref_p@10 of {value, P@10} -> erlang:element(3, P@10) =:= in_query; _ -> false end end ) end ), Uses_headers = Has_multipart_body orelse gleam@list:any( Operations, fun(Op@14) -> {_, Operation@14, _, _} = Op@14, gleam@list:any( erlang:element(6, Operation@14), fun(Ref_p@11) -> case Ref_p@11 of {value, P@11} -> (erlang:element(3, P@11) =:= in_header) orelse (erlang:element( 3, P@11 ) =:= in_cookie); _ -> false end end ) end ), Uses_body = gleam@list:any( Operations, fun(Op@15) -> {_, Operation@15, _, _} = Op@15, gleam@option:is_some(erlang:element(7, Operation@15)) end ), Has_params_ops = gleam@list:any( Operations, fun(Op@16) -> {_, Operation@16, _, _} = Op@16, not gleam@list:is_empty(erlang:element(6, Operation@16)) orelse gleam@option:is_some( erlang:element(7, Operation@16) ) end ), _ = Needs_dict, Std_imports = [<<"gleam/dict.{type Dict}"/utf8>>], Std_imports@1 = case Needs_list_import of true -> lists:append(Std_imports, [<<"gleam/list"/utf8>>]); false -> Std_imports end, Std_imports@2 = case Needs_uri_import of true -> lists:append(Std_imports@1, [<<"gleam/uri"/utf8>>]); false -> Std_imports@1 end, Std_imports@3 = case Needs_int of true -> lists:append(Std_imports@2, [<<"gleam/int"/utf8>>]); false -> Std_imports@2 end, Std_imports@4 = case Needs_float of true -> lists:append(Std_imports@3, [<<"gleam/float"/utf8>>]); false -> Std_imports@3 end, Std_imports@5 = case Needs_option of true -> lists:append(Std_imports@4, [<<"gleam/option.{None, Some}"/utf8>>]); false -> Std_imports@4 end, Std_imports@6 = case Needs_json of true -> lists:append(Std_imports@5, [<<"gleam/json"/utf8>>]); false -> Std_imports@5 end, Std_imports@7 = case Needs_string of true -> lists:append(Std_imports@6, [<<"gleam/string"/utf8>>]); false -> Std_imports@6 end, Pkg_imports = [<<(erlang:element(5, erlang:element(3, Ctx)))/binary, "/handlers"/utf8>>], Pkg_imports@1 = case (Has_deep_object orelse Has_form_urlencoded_body) orelse Has_multipart_body of true -> lists:append( Pkg_imports, [<<(erlang:element(5, erlang:element(3, Ctx)))/binary, "/types"/utf8>>] ); false -> Pkg_imports end, Pkg_imports@2 = case Needs_decode of true -> lists:append( Pkg_imports@1, [<<(erlang:element(5, erlang:element(3, Ctx)))/binary, "/decode"/utf8>>] ); false -> Pkg_imports@1 end, Pkg_imports@3 = case Needs_encode of true -> lists:append( Pkg_imports@2, [<<(erlang:element(5, erlang:element(3, Ctx)))/binary, "/encode"/utf8>>] ); false -> Pkg_imports@2 end, Pkg_imports@4 = case Has_params_ops of true -> lists:append( Pkg_imports@3, [<<(erlang:element(5, erlang:element(3, Ctx)))/binary, "/request_types"/utf8>>, <<(erlang:element(5, erlang:element(3, Ctx)))/binary, "/response_types"/utf8>>] ); false -> lists:append( Pkg_imports@3, [<<(erlang:element(5, erlang:element(3, Ctx)))/binary, "/response_types"/utf8>>] ) end, All_imports = lists:append(Std_imports@7, Pkg_imports@4), Sb = begin _pipe = oaspec@util@string_extra:file_header(<<"0.10.0"/utf8>>), oaspec@util@string_extra:imports(_pipe, All_imports) end, Sb@1 = begin _pipe@1 = Sb, _pipe@2 = oaspec@util@string_extra:doc_comment( _pipe@1, <<"A server response with status code, body, and headers."/utf8>> ), _pipe@3 = oaspec@util@string_extra:line( _pipe@2, <<"pub type ServerResponse {"/utf8>> ), _pipe@4 = oaspec@util@string_extra:indent( _pipe@3, 1, <<"ServerResponse(status: Int, body: String, headers: List(#(String, String)))"/utf8>> ), _pipe@5 = oaspec@util@string_extra:line(_pipe@4, <<"}"/utf8>>), oaspec@util@string_extra:blank_line(_pipe@5) end, Sb@2 = case Has_deep_object of true -> _pipe@6 = Sb@1, _pipe@7 = oaspec@util@string_extra:line( _pipe@6, <<"fn deep_object_present(query: Dict(String, List(String)), prefix: String, props: List(String)) -> Bool {"/utf8>> ), _pipe@8 = oaspec@util@string_extra:indent( _pipe@7, 1, <<"list.any(props, fn(prop) { dict.has_key(query, prefix <> \"[\" <> prop <> \"]\") })"/utf8>> ), _pipe@9 = oaspec@util@string_extra:line(_pipe@8, <<"}"/utf8>>), oaspec@util@string_extra:blank_line(_pipe@9); false -> Sb@1 end, Sb@3 = case Has_form_urlencoded_body of true -> _pipe@10 = Sb@2, _pipe@11 = oaspec@util@string_extra:line( _pipe@10, <<"fn form_url_decode(value: String) -> String {"/utf8>> ), _pipe@12 = oaspec@util@string_extra:indent( _pipe@11, 1, <<"let value = string.replace(value, \"+\", \" \")"/utf8>> ), _pipe@13 = oaspec@util@string_extra:indent( _pipe@12, 1, <<"case uri.percent_decode(value) { Ok(decoded) -> decoded Error(_) -> value }"/utf8>> ), _pipe@14 = oaspec@util@string_extra:line(_pipe@13, <<"}"/utf8>>), _pipe@15 = oaspec@util@string_extra:blank_line(_pipe@14), _pipe@16 = oaspec@util@string_extra:line( _pipe@15, <<"fn parse_form_body(body: String) -> Dict(String, List(String)) {"/utf8>> ), _pipe@17 = oaspec@util@string_extra:indent( _pipe@16, 1, <<"let parts = case body { \"\" -> [] _ -> string.split(body, \"&\") }"/utf8>> ), _pipe@18 = oaspec@util@string_extra:indent( _pipe@17, 1, <<"list.fold(parts, dict.new(), fn(acc, part) {"/utf8>> ), _pipe@19 = oaspec@util@string_extra:indent( _pipe@18, 2, <<"case part {"/utf8>> ), _pipe@20 = oaspec@util@string_extra:indent( _pipe@19, 3, <<"\"\" -> acc"/utf8>> ), _pipe@21 = oaspec@util@string_extra:indent( _pipe@20, 3, <<"_ ->"/utf8>> ), _pipe@22 = oaspec@util@string_extra:indent( _pipe@21, 4, <<"case string.split_once(part, on: \"=\") {"/utf8>> ), _pipe@23 = oaspec@util@string_extra:indent( _pipe@22, 5, <<"Ok(#(raw_key, raw_value)) -> {"/utf8>> ), _pipe@24 = oaspec@util@string_extra:indent( _pipe@23, 6, <<"let key = form_url_decode(raw_key)"/utf8>> ), _pipe@25 = oaspec@util@string_extra:indent( _pipe@24, 6, <<"let value = form_url_decode(raw_value)"/utf8>> ), _pipe@26 = oaspec@util@string_extra:indent( _pipe@25, 6, <<"case dict.get(acc, key) {"/utf8>> ), _pipe@27 = oaspec@util@string_extra:indent( _pipe@26, 7, <<"Ok(existing) -> dict.insert(acc, key, list.append(existing, [value]))"/utf8>> ), _pipe@28 = oaspec@util@string_extra:indent( _pipe@27, 7, <<"Error(_) -> dict.insert(acc, key, [value])"/utf8>> ), _pipe@29 = oaspec@util@string_extra:indent( _pipe@28, 6, <<"}"/utf8>> ), _pipe@30 = oaspec@util@string_extra:indent( _pipe@29, 5, <<"}"/utf8>> ), _pipe@31 = oaspec@util@string_extra:indent( _pipe@30, 5, <<"Error(_) -> {"/utf8>> ), _pipe@32 = oaspec@util@string_extra:indent( _pipe@31, 6, <<"let key = form_url_decode(part)"/utf8>> ), _pipe@33 = oaspec@util@string_extra:indent( _pipe@32, 6, <<"case dict.get(acc, key) {"/utf8>> ), _pipe@34 = oaspec@util@string_extra:indent( _pipe@33, 7, <<"Ok(existing) -> dict.insert(acc, key, list.append(existing, [\"\"]))"/utf8>> ), _pipe@35 = oaspec@util@string_extra:indent( _pipe@34, 7, <<"Error(_) -> dict.insert(acc, key, [\"\"])"/utf8>> ), _pipe@36 = oaspec@util@string_extra:indent( _pipe@35, 6, <<"}"/utf8>> ), _pipe@37 = oaspec@util@string_extra:indent( _pipe@36, 5, <<"}"/utf8>> ), _pipe@38 = oaspec@util@string_extra:indent( _pipe@37, 4, <<"}"/utf8>> ), _pipe@39 = oaspec@util@string_extra:indent( _pipe@38, 2, <<"}"/utf8>> ), _pipe@40 = oaspec@util@string_extra:indent( _pipe@39, 1, <<"})"/utf8>> ), _pipe@41 = oaspec@util@string_extra:line(_pipe@40, <<"}"/utf8>>), oaspec@util@string_extra:blank_line(_pipe@41); false -> Sb@2 end, Sb@4 = case Has_multipart_body of true -> _pipe@42 = Sb@3, _pipe@43 = oaspec@util@string_extra:line( _pipe@42, <<"fn multipart_boundary(headers: Dict(String, String)) -> Result(String, Nil) {"/utf8>> ), _pipe@44 = oaspec@util@string_extra:indent( _pipe@43, 1, <<"case dict.get(headers, \"content-type\") {"/utf8>> ), _pipe@45 = oaspec@util@string_extra:indent( _pipe@44, 2, <<"Ok(content_type) ->"/utf8>> ), _pipe@46 = oaspec@util@string_extra:indent( _pipe@45, 3, <<"list.find_map(string.split(content_type, \";\"), fn(part) {"/utf8>> ), _pipe@47 = oaspec@util@string_extra:indent( _pipe@46, 4, <<"let trimmed = string.trim(part)"/utf8>> ), _pipe@48 = oaspec@util@string_extra:indent( _pipe@47, 4, <<"case string.starts_with(trimmed, \"boundary=\") {"/utf8>> ), _pipe@49 = oaspec@util@string_extra:indent( _pipe@48, 5, <<"True -> Ok(string.replace(trimmed, \"boundary=\", \"\"))"/utf8>> ), _pipe@50 = oaspec@util@string_extra:indent( _pipe@49, 5, <<"False -> Error(Nil)"/utf8>> ), _pipe@51 = oaspec@util@string_extra:indent( _pipe@50, 4, <<"}"/utf8>> ), _pipe@52 = oaspec@util@string_extra:indent( _pipe@51, 3, <<"})"/utf8>> ), _pipe@53 = oaspec@util@string_extra:indent( _pipe@52, 2, <<"Error(_) -> Error(Nil)"/utf8>> ), _pipe@54 = oaspec@util@string_extra:indent( _pipe@53, 1, <<"}"/utf8>> ), _pipe@55 = oaspec@util@string_extra:line(_pipe@54, <<"}"/utf8>>), _pipe@56 = oaspec@util@string_extra:blank_line(_pipe@55), _pipe@57 = oaspec@util@string_extra:line( _pipe@56, <<"fn multipart_name(raw_headers: String) -> Result(String, Nil) {"/utf8>> ), _pipe@58 = oaspec@util@string_extra:indent( _pipe@57, 1, <<"list.find_map(string.split(raw_headers, \"\\r\\n\"), fn(line) {"/utf8>> ), _pipe@59 = oaspec@util@string_extra:indent( _pipe@58, 2, <<"case string.contains(line, \"name=\") {"/utf8>> ), _pipe@60 = oaspec@util@string_extra:indent( _pipe@59, 3, <<"True ->"/utf8>> ), _pipe@61 = oaspec@util@string_extra:indent( _pipe@60, 4, <<"list.find_map(string.split(line, \";\"), fn(part) {"/utf8>> ), _pipe@62 = oaspec@util@string_extra:indent( _pipe@61, 5, <<"let trimmed = string.trim(part)"/utf8>> ), _pipe@63 = oaspec@util@string_extra:indent( _pipe@62, 5, <<"case string.starts_with(trimmed, \"name=\") {"/utf8>> ), _pipe@64 = oaspec@util@string_extra:indent( _pipe@63, 6, <<"True -> Ok(string.replace(string.replace(trimmed, \"name=\", \"\"), \"\\\"\", \"\"))"/utf8>> ), _pipe@65 = oaspec@util@string_extra:indent( _pipe@64, 6, <<"False -> Error(Nil)"/utf8>> ), _pipe@66 = oaspec@util@string_extra:indent( _pipe@65, 5, <<"}"/utf8>> ), _pipe@67 = oaspec@util@string_extra:indent( _pipe@66, 4, <<"})"/utf8>> ), _pipe@68 = oaspec@util@string_extra:indent( _pipe@67, 3, <<"False -> Error(Nil)"/utf8>> ), _pipe@69 = oaspec@util@string_extra:indent( _pipe@68, 2, <<"}"/utf8>> ), _pipe@70 = oaspec@util@string_extra:indent( _pipe@69, 1, <<"})"/utf8>> ), _pipe@71 = oaspec@util@string_extra:line(_pipe@70, <<"}"/utf8>>), _pipe@72 = oaspec@util@string_extra:blank_line(_pipe@71), _pipe@73 = oaspec@util@string_extra:line( _pipe@72, <<"fn parse_multipart_body(body: String, headers: Dict(String, String)) -> Dict(String, List(String)) {"/utf8>> ), _pipe@74 = oaspec@util@string_extra:indent( _pipe@73, 1, <<"case multipart_boundary(headers) {"/utf8>> ), _pipe@75 = oaspec@util@string_extra:indent( _pipe@74, 2, <<"Ok(boundary) -> {"/utf8>> ), _pipe@76 = oaspec@util@string_extra:indent( _pipe@75, 3, <<"let delimiter = \"--\" <> boundary"/utf8>> ), _pipe@77 = oaspec@util@string_extra:indent( _pipe@76, 3, <<"let parts = string.split(body, delimiter)"/utf8>> ), _pipe@78 = oaspec@util@string_extra:indent( _pipe@77, 3, <<"list.fold(parts, dict.new(), fn(acc, part) {"/utf8>> ), _pipe@79 = oaspec@util@string_extra:indent( _pipe@78, 4, <<"let normalized_part = part |> string.remove_prefix(\"\\r\\n\") |> string.remove_suffix(\"\\r\\n\")"/utf8>> ), _pipe@80 = oaspec@util@string_extra:indent( _pipe@79, 4, <<"case normalized_part == \"\" || normalized_part == \"--\" {"/utf8>> ), _pipe@81 = oaspec@util@string_extra:indent( _pipe@80, 5, <<"True -> acc"/utf8>> ), _pipe@82 = oaspec@util@string_extra:indent( _pipe@81, 5, <<"False ->"/utf8>> ), _pipe@83 = oaspec@util@string_extra:indent( _pipe@82, 6, <<"case string.split_once(normalized_part, on: \"\\r\\n\\r\\n\") {"/utf8>> ), _pipe@84 = oaspec@util@string_extra:indent( _pipe@83, 7, <<"Ok(#(raw_part_headers, raw_value)) ->"/utf8>> ), _pipe@85 = oaspec@util@string_extra:indent( _pipe@84, 8, <<"case multipart_name(raw_part_headers) {"/utf8>> ), _pipe@86 = oaspec@util@string_extra:indent( _pipe@85, 9, <<"Ok(name) -> {"/utf8>> ), _pipe@87 = oaspec@util@string_extra:indent( _pipe@86, 10, <<"let value = raw_value"/utf8>> ), _pipe@88 = oaspec@util@string_extra:indent( _pipe@87, 10, <<"case dict.get(acc, name) {"/utf8>> ), _pipe@89 = oaspec@util@string_extra:indent( _pipe@88, 11, <<"Ok(existing) -> dict.insert(acc, name, list.append(existing, [value]))"/utf8>> ), _pipe@90 = oaspec@util@string_extra:indent( _pipe@89, 11, <<"Error(_) -> dict.insert(acc, name, [value])"/utf8>> ), _pipe@91 = oaspec@util@string_extra:indent( _pipe@90, 10, <<"}"/utf8>> ), _pipe@92 = oaspec@util@string_extra:indent( _pipe@91, 9, <<"}"/utf8>> ), _pipe@93 = oaspec@util@string_extra:indent( _pipe@92, 9, <<"Error(_) -> acc"/utf8>> ), _pipe@94 = oaspec@util@string_extra:indent( _pipe@93, 8, <<"}"/utf8>> ), _pipe@95 = oaspec@util@string_extra:indent( _pipe@94, 7, <<"Error(_) -> acc"/utf8>> ), _pipe@96 = oaspec@util@string_extra:indent( _pipe@95, 6, <<"}"/utf8>> ), _pipe@97 = oaspec@util@string_extra:indent( _pipe@96, 4, <<"}"/utf8>> ), _pipe@98 = oaspec@util@string_extra:indent( _pipe@97, 3, <<"})"/utf8>> ), _pipe@99 = oaspec@util@string_extra:indent( _pipe@98, 2, <<"}"/utf8>> ), _pipe@100 = oaspec@util@string_extra:indent( _pipe@99, 2, <<"Error(_) -> dict.new()"/utf8>> ), _pipe@101 = oaspec@util@string_extra:indent( _pipe@100, 1, <<"}"/utf8>> ), _pipe@102 = oaspec@util@string_extra:line(_pipe@101, <<"}"/utf8>>), oaspec@util@string_extra:blank_line(_pipe@102); false -> Sb@3 end, Sb@5 = case Has_nested_form_urlencoded_body of true -> _pipe@103 = Sb@4, _pipe@104 = oaspec@util@string_extra:line( _pipe@103, <<"fn form_object_present(form_body: Dict(String, List(String)), prefix: String, props: List(String)) -> Bool {"/utf8>> ), _pipe@105 = oaspec@util@string_extra:indent( _pipe@104, 1, <<"list.any(props, fn(prop) { dict.has_key(form_body, prefix <> \"[\" <> prop <> \"]\") })"/utf8>> ), _pipe@106 = oaspec@util@string_extra:line(_pipe@105, <<"}"/utf8>>), oaspec@util@string_extra:blank_line(_pipe@106); false -> Sb@4 end, Sb@6 = begin _pipe@107 = Sb@5, _pipe@108 = oaspec@util@string_extra:doc_comment( _pipe@107, <<"Route an incoming request to the appropriate handler."/utf8>> ), _pipe@109 = oaspec@util@string_extra:line( _pipe@108, <<<<<<<<<<<<"pub fn route(method: String, path: List(String), "/utf8, (route_arg_name( <<"query"/utf8>>, Uses_query ))/binary>>/binary, ": Dict(String, List(String)), "/utf8>>/binary, (route_arg_name(<<"headers"/utf8>>, Uses_headers))/binary>>/binary, ": Dict(String, String), "/utf8>>/binary, (route_arg_name(<<"body"/utf8>>, Uses_body))/binary>>/binary, ": String) -> ServerResponse {"/utf8>> ), oaspec@util@string_extra:indent( _pipe@109, 1, <<"case method, path {"/utf8>> ) end, Sb@8 = gleam@list:fold( Operations, Sb@6, fun(Sb@7, Op@17) -> {Op_id, Operation@17, Path, Method} = Op@17, Fn_name = oaspec@util@naming:operation_to_function_name(Op_id), Method_str = oaspec@openapi@spec:method_to_string(Method), Path_pattern = path_to_pattern(Path), Has_params = not gleam@list:is_empty( erlang:element(6, Operation@17) ) orelse gleam@option:is_some(erlang:element(7, Operation@17)), _pipe@110 = Sb@7, _pipe@111 = oaspec@util@string_extra:indent( _pipe@110, 2, <<<<<<<<"\""/utf8, Method_str/binary>>/binary, "\", "/utf8>>/binary, Path_pattern/binary>>/binary, " -> {"/utf8>> ), _pipe@112 = generate_route_body( _pipe@111, Op_id, Fn_name, Operation@17, Path, Has_params, Ctx ), oaspec@util@string_extra:indent(_pipe@112, 2, <<"}"/utf8>>) end ), Sb@9 = begin _pipe@113 = Sb@8, _pipe@114 = oaspec@util@string_extra:indent( _pipe@113, 2, <<"_, _ -> ServerResponse(status: 404, body: \"Not Found\", headers: [])"/utf8>> ), _pipe@115 = oaspec@util@string_extra:indent(_pipe@114, 1, <<"}"/utf8>>), _pipe@116 = oaspec@util@string_extra:line(_pipe@115, <<"}"/utf8>>), oaspec@util@string_extra:blank_line(_pipe@116) end, Sb@10 = case Needs_cookie_lookup of true -> generate_cookie_lookup(Sb@9); false -> Sb@9 end, oaspec@util@string_extra:to_string(Sb@10). -file("src/oaspec/codegen/server.gleam", 16). ?DOC(" Generate server stub files.\n"). -spec generate(oaspec@codegen@context:context()) -> list(oaspec@codegen@context:generated_file()). generate(Ctx) -> Handlers_content = generate_handlers(Ctx), Router_content = generate_router(Ctx), [{generated_file, <<"handlers.gleam"/utf8>>, Handlers_content, server_target}, {generated_file, <<"router.gleam"/utf8>>, Router_content, server_target}].