-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", 60). ?DOC(" Generate a single handler stub.\n"). -spec generate_handler( gleam@string_tree:string_tree(), binary(), oaspec@openapi@spec:operation(), 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, <<"// TODO: Implement "/utf8, Fn_name/binary>> ), _pipe@7 = oaspec@util@string_extra:indent(_pipe@6, 1, <<"todo"/utf8>>), _pipe@8 = oaspec@util@string_extra:line(_pipe@7, <<"}"/utf8>>), oaspec@util@string_extra:blank_line(_pipe@8). -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", 115). ?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() ) -> gleam@string_tree:string_tree(). generate_callback_handlers(Sb, Op_id, Operation) -> Callbacks = maps:to_list(erlang:element(11, Operation)), gleam@list:fold( Callbacks, Sb, fun(Sb@1, Entry) -> {Callback_name, Callback} = Entry, Callback_entries = maps:to_list(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, <<"// TODO: Implement callback "/utf8, Callback_name/binary>> ), _pipe@5 = oaspec@util@string_extra:indent( _pipe@4, 1, <<"todo"/utf8>> ), _pipe@6 = oaspec@util@string_extra:line( _pipe@5, <<"}"/utf8>> ), oaspec@util@string_extra:blank_line(_pipe@6) end ) end ). -file("src/oaspec/codegen/server.gleam", 33). ?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.5.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@codegen@types: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", 460). ?DOC(" Generate parse expression for a path parameter (already bound as String).\n"). -spec param_parse_expr(binary(), oaspec@openapi@spec:parameter()) -> binary(). param_parse_expr(Var_name, Param) -> case erlang:element(6, Param) of {some, {inline, {integer_schema, _, _, _, _, _, _, _}}} -> <<<<"{ let assert Ok(v) = int.parse("/utf8, Var_name/binary>>/binary, ") v }"/utf8>>; {some, {inline, {number_schema, _, _, _, _, _, _, _}}} -> <>; {some, {inline, {boolean_schema, _}}} -> <<<<"case "/utf8, Var_name/binary>>/binary, " { \"true\" -> True _ -> False }"/utf8>>; _ -> Var_name end. -file("src/oaspec/codegen/server.gleam", 477). ?DOC(" Generate expression for a required query parameter.\n"). -spec query_required_expr(binary(), oaspec@openapi@spec:parameter()) -> binary(). query_required_expr(Key, Param) -> Base = <<<<"{ let assert Ok(v) = dict.get(query, \""/utf8, Key/binary>>/binary, "\") v }"/utf8>>, case erlang:element(6, Param) of {some, {inline, {integer_schema, _, _, _, _, _, _, _}}} -> <<<<"{ let assert Ok(v) = dict.get(query, \""/utf8, Key/binary>>/binary, "\") let assert Ok(n) = int.parse(v) n }"/utf8>>; {some, {inline, {boolean_schema, _}}} -> <<<<"{ let assert Ok(v) = dict.get(query, \""/utf8, Key/binary>>/binary, "\") case v { \"true\" -> True _ -> False } }"/utf8>>; _ -> Base end. -file("src/oaspec/codegen/server.gleam", 493). ?DOC(" Generate expression for an optional query parameter.\n"). -spec query_optional_expr(binary(), oaspec@openapi@spec:parameter()) -> binary(). query_optional_expr(Key, Param) -> case erlang:element(6, Param) of {some, {inline, {integer_schema, _, _, _, _, _, _, _}}} -> <<<<"case dict.get(query, \""/utf8, Key/binary>>/binary, "\") { Ok(v) -> { case int.parse(v) { Ok(n) -> Some(n) _ -> None } } _ -> None }"/utf8>>; {some, {inline, {boolean_schema, _}}} -> <<<<"case dict.get(query, \""/utf8, Key/binary>>/binary, "\") { Ok(v) -> Some(case v { \"true\" -> True _ -> False }) _ -> None }"/utf8>>; _ -> <<<<"case dict.get(query, \""/utf8, Key/binary>>/binary, "\") { Ok(v) -> Some(v) _ -> None }"/utf8>> end. -file("src/oaspec/codegen/server.gleam", 509). ?DOC(" Generate expression for a required header parameter.\n"). -spec header_required_expr(binary(), oaspec@openapi@spec:parameter()) -> binary(). header_required_expr(Key, Param) -> case erlang:element(6, Param) of {some, {inline, {integer_schema, _, _, _, _, _, _, _}}} -> <<<<"{ let assert Ok(v) = dict.get(headers, \""/utf8, Key/binary>>/binary, "\") let assert Ok(n) = int.parse(v) n }"/utf8>>; _ -> <<<<"{ let assert Ok(v) = dict.get(headers, \""/utf8, Key/binary>>/binary, "\") v }"/utf8>> end. -file("src/oaspec/codegen/server.gleam", 520). ?DOC(" Generate expression for an optional header parameter.\n"). -spec header_optional_expr(binary(), oaspec@openapi@spec:parameter()) -> binary(). header_optional_expr(Key, Param) -> case erlang:element(6, Param) of {some, {inline, {integer_schema, _, _, _, _, _, _, _}}} -> <<<<"case dict.get(headers, \""/utf8, Key/binary>>/binary, "\") { Ok(v) -> { case int.parse(v) { Ok(n) -> Some(n) _ -> None } } _ -> None }"/utf8>>; _ -> <<<<"case dict.get(headers, \""/utf8, Key/binary>>/binary, "\") { Ok(v) -> Some(v) _ -> None }"/utf8>> end. -file("src/oaspec/codegen/server.gleam", 532). ?DOC(" Generate the body decode expression for a request body.\n"). -spec generate_body_decode_expr(oaspec@openapi@spec:request_body(), binary()) -> binary(). generate_body_decode_expr(Rb, Op_id) -> Content_entries = maps:to_list(erlang:element(3, Rb)), case Content_entries of [{<<"application/json"/utf8>>, Media_type}] -> Decode_fn = case erlang:element(2, Media_type) of {some, {reference, _, Name}} -> <<<<"decode.decode_"/utf8, (oaspec@util@naming:to_snake_case(Name))/binary>>/binary, "(body)"/utf8>>; _ -> <<<<"decode.decode_"/utf8, (oaspec@util@naming:to_snake_case(Op_id))/binary>>/binary, "_request_body(body)"/utf8>> end, case erlang:element(4, Rb) of true -> <<<<"{ let assert Ok(decoded) = "/utf8, Decode_fn/binary>>/binary, " decoded }"/utf8>>; false -> <<<<"case body { \"\" -> None _ -> { case "/utf8, Decode_fn/binary>>/binary, " { Ok(decoded) -> Some(decoded) _ -> None } } }"/utf8>> end; _ -> case erlang:element(4, Rb) of true -> <<"body"/utf8>>; false -> <<"case body { \"\" -> None _ -> Some(body) }"/utf8>> end end. -file("src/oaspec/codegen/server.gleam", 706). ?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", 562). ?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@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, Response} = Entry, 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; [_, _ | _] -> _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: [])"/utf8>> ) end end ), _pipe@10 = Sb@3, oaspec@util@string_extra:indent(_pipe@10, 3, <<"}"/utf8>>) end. -file("src/oaspec/codegen/server.gleam", 753). ?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", 761). ?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", 368). ?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(), binary(), oaspec@codegen@context:context() ) -> gleam@string_tree:string_tree(). generate_request_construction(Sb, Request_type_name, Op_id, Operation, Path, _) -> Path_segments = begin _pipe = Path, _pipe@1 = gleam@string:split(_pipe, <<"/"/utf8>>), gleam@list:filter(_pipe@1, fun(S) -> S /= <<""/utf8>> end) end, Path_param_indices = begin _pipe@2 = gleam@list:index_map( Path_segments, fun(Seg, Idx) -> {Seg, Idx} end ), _pipe@3 = gleam@list:filter( _pipe@2, fun(Entry) -> {Seg@1, _} = Entry, is_path_param(Seg@1) end ), gleam@list:map( _pipe@3, fun(Entry@1) -> {Seg@2, Idx@1} = Entry@1, Name = extract_param_name(Seg@2), {Name, Idx@1} end ) end, Sb@2 = gleam@list:fold( Path_param_indices, Sb, fun(Sb@1, Entry@2) -> {Name@1, _} = Entry@2, Var_name = <<(oaspec@util@naming:to_snake_case(Name@1))/binary, "_param"/utf8>>, _ = Var_name, Sb@1 end ), Sb@3 = begin _pipe@4 = Sb@2, oaspec@util@string_extra:indent( _pipe@4, 3, <<<<"let request = request_types."/utf8, Request_type_name/binary>>/binary, "("/utf8>> ) end, Params = erlang:element(6, Operation), Sb@5 = gleam@list:index_fold( Params, Sb@3, fun(Sb@4, 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@1 = oaspec@util@naming:to_snake_case( erlang:element(2, Param) ), param_parse_expr(Var_name@1, Param); in_query -> Key = erlang:element(2, Param), case erlang:element(5, Param) of true -> query_required_expr(Key, Param); false -> query_optional_expr(Key, Param) end; in_header -> Key@1 = erlang:element(2, Param), case erlang:element(5, Param) of true -> header_required_expr(Key@1, Param); false -> header_optional_expr(Key@1, Param) end; in_cookie -> case erlang:element(5, Param) of true -> <<"\"\" // TODO: Extract cookie param "/utf8, (erlang:element(2, Param))/binary>>; false -> <<"None // TODO: Extract cookie param "/utf8, (erlang:element(2, Param))/binary>> end end, _pipe@5 = Sb@4, oaspec@util@string_extra:indent( _pipe@5, 4, <<<<<>/binary, Value_expr/binary>>/binary, Trailing/binary>> ) end ), Sb@6 = case erlang:element(7, Operation) of {some, Rb} -> Body_expr = generate_body_decode_expr(Rb, Op_id), _pipe@6 = Sb@5, oaspec@util@string_extra:indent( _pipe@6, 4, <<<<"body: "/utf8, Body_expr/binary>>/binary, ","/utf8>> ); none -> Sb@5 end, _pipe@7 = Sb@6, oaspec@util@string_extra:indent(_pipe@7, 3, <<")"/utf8>>). -file("src/oaspec/codegen/server.gleam", 329). ?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(), 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", 732). ?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@codegen@types:collect_operations(Ctx), Needs_dict = gleam@list:any( Operations, fun(Op) -> {_, Operation, _, _} = Op, Has_query = gleam@list:any( erlang:element(6, Operation), fun(P) -> erlang:element(3, P) =:= in_query end ), Has_header = gleam@list:any( erlang:element(6, Operation), fun(P@1) -> erlang:element(3, P@1) =:= in_header end ), Has_query orelse Has_header end ), Needs_int = gleam@list:any( Operations, fun(Op@1) -> {_, Operation@1, _, _} = Op@1, gleam@list:any( erlang:element(6, Operation@1), fun(P@2) -> case erlang:element(6, P@2) of {some, {inline, {integer_schema, _, _, _, _, _, _, _}}} -> true; _ -> false end end ) end ), Needs_option = gleam@list:any( Operations, fun(Op@2) -> {_, Operation@2, _, _} = Op@2, Has_optional_params = gleam@list:any( erlang:element(6, Operation@2), fun(P@3) -> not erlang:element(5, P@3) end ), Has_optional_body = case erlang:element(7, Operation@2) of {some, Rb} -> not erlang:element(4, Rb); none -> false end, Has_optional_params orelse Has_optional_body end ), Needs_json = gleam@list:any( Operations, fun(Op@3) -> {_, Operation@3, _, _} = Op@3, Responses = maps:to_list(erlang:element(8, Operation@3)), gleam@list:any( Responses, fun(Entry) -> {_, Response} = Entry, 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 end ) end ), Needs_decode = Needs_json andalso gleam@list:any( Operations, fun(Op@4) -> {_, Operation@4, _, _} = Op@4, gleam@option:is_some(erlang:element(7, Operation@4)) end ), Needs_encode = Needs_json, Has_params_ops = gleam@list:any( Operations, fun(Op@5) -> {_, Operation@5, _, _} = Op@5, not gleam@list:is_empty(erlang:element(6, Operation@5)) orelse gleam@option:is_some( erlang:element(7, Operation@5) ) end ), _ = Needs_dict, Std_imports = [<<"gleam/dict.{type Dict}"/utf8>>], Std_imports@1 = case Needs_int of true -> lists:append(Std_imports, [<<"gleam/int"/utf8>>]); false -> Std_imports end, Std_imports@2 = case Needs_option of true -> lists:append(Std_imports@1, [<<"gleam/option.{None, Some}"/utf8>>]); false -> Std_imports@1 end, Std_imports@3 = case Needs_json of true -> lists:append(Std_imports@2, [<<"gleam/json"/utf8>>]); false -> Std_imports@2 end, Pkg_imports = [<<(erlang:element(5, erlang:element(3, Ctx)))/binary, "/handlers"/utf8>>], Pkg_imports@1 = case Needs_decode of true -> lists:append( Pkg_imports, [<<(erlang:element(5, erlang:element(3, Ctx)))/binary, "/decode"/utf8>>] ); false -> Pkg_imports end, Pkg_imports@2 = case Needs_encode of true -> lists:append( Pkg_imports@1, [<<(erlang:element(5, erlang:element(3, Ctx)))/binary, "/encode"/utf8>>] ); false -> Pkg_imports@1 end, Pkg_imports@3 = case Has_params_ops of true -> lists:append( Pkg_imports@2, [<<(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@2, [<<(erlang:element(5, erlang:element(3, Ctx)))/binary, "/response_types"/utf8>>] ) end, All_imports = lists:append(Std_imports@3, Pkg_imports@3), Sb = begin _pipe = oaspec@util@string_extra:file_header(<<"0.5.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 = begin _pipe@6 = Sb@1, _pipe@7 = oaspec@util@string_extra:doc_comment( _pipe@6, <<"Route an incoming request to the appropriate handler."/utf8>> ), _pipe@8 = oaspec@util@string_extra:line( _pipe@7, <<"pub fn route(method: String, path: List(String), query: Dict(String, String), headers: Dict(String, String), body: String) -> ServerResponse {"/utf8>> ), oaspec@util@string_extra:indent( _pipe@8, 1, <<"case method, path {"/utf8>> ) end, Sb@4 = gleam@list:fold( Operations, Sb@2, fun(Sb@3, Op@6) -> {Op_id, Operation@6, Path, Method} = Op@6, 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@6)) orelse gleam@option:is_some(erlang:element(7, Operation@6)), _pipe@9 = Sb@3, _pipe@10 = oaspec@util@string_extra:indent( _pipe@9, 2, <<<<<<<<"\""/utf8, Method_str/binary>>/binary, "\", "/utf8>>/binary, Path_pattern/binary>>/binary, " -> {"/utf8>> ), _pipe@11 = generate_route_body( _pipe@10, Op_id, Fn_name, Operation@6, Path, Has_params, Ctx ), oaspec@util@string_extra:indent(_pipe@11, 2, <<"}"/utf8>>) end ), Sb@5 = begin _pipe@12 = Sb@4, _pipe@13 = oaspec@util@string_extra:indent( _pipe@12, 2, <<"_, _ -> ServerResponse(status: 404, body: \"Not Found\", headers: [])"/utf8>> ), _pipe@14 = oaspec@util@string_extra:indent(_pipe@13, 1, <<"}"/utf8>>), _pipe@15 = oaspec@util@string_extra:line(_pipe@14, <<"}"/utf8>>), oaspec@util@string_extra:blank_line(_pipe@15) end, oaspec@util@string_extra:to_string(Sb@5). -file("src/oaspec/codegen/server.gleam", 14). ?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}].