-module(oaspec@internal@codegen@client_response). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/oaspec/internal/codegen/client_response.gleam"). -export([generate_empty_content_response/4, generate_multi_content_response/7, build_headers_record/3, inline_schema_to_decoder/1, get_response_decode_expr/4, generate_single_content_response/8]). -export_type([headers_record/0, header_field_type/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 headers_record() :: {headers_record, list(binary()), binary()}. -type header_field_type() :: string_header | int_header | float_header | bool_header. -file("src/oaspec/internal/codegen/client_response.gleam", 23). ?DOC(false). -spec status_branch_pattern(oaspec@internal@util@http:http_status_code()) -> binary(). status_branch_pattern(Status_code) -> case Status_code of default_status -> <<"status"/utf8>>; _ -> oaspec@internal@util@http:status_code_to_int_pattern(Status_code) end. -file("src/oaspec/internal/codegen/client_response.gleam", 33). ?DOC(false). -spec prepend_default_status( binary(), oaspec@internal@util@http:http_status_code() ) -> binary(). prepend_default_status(Arg, Status_code) -> case Status_code of default_status -> case Arg of <<""/utf8>> -> <<"status"/utf8>>; _ -> <<"status, "/utf8, Arg/binary>> end; _ -> Arg end. -file("src/oaspec/internal/codegen/client_response.gleam", 219). ?DOC(false). -spec emit_pre_statements( gleam@string_tree:string_tree(), gleam@option:option(headers_record()) ) -> gleam@string_tree:string_tree(). emit_pre_statements(Sb, Headers) -> case Headers of {some, {headers_record, Stmts, _}} -> gleam@list:fold( Stmts, Sb, fun(Acc, Line) -> oaspec@internal@util@string_extra:indent(Acc, 3, Line) end ); none -> Sb end. -file("src/oaspec/internal/codegen/client_response.gleam", 169). ?DOC(false). -spec empty_body_branch( gleam@string_tree:string_tree(), oaspec@internal@util@http:http_status_code(), binary(), gleam@option:option(headers_record()) ) -> gleam@string_tree:string_tree(). empty_body_branch(Sb, Status_code, Variant_name, Headers) -> case Headers of {some, {headers_record, [_ | _], Expr}} -> _pipe = Sb, _pipe@1 = oaspec@internal@util@string_extra:indent( _pipe, 2, <<(status_branch_pattern(Status_code))/binary, " -> {"/utf8>> ), _pipe@2 = emit_pre_statements(_pipe@1, Headers), _pipe@3 = oaspec@internal@util@string_extra:indent( _pipe@2, 3, <<<<<<<<"Ok("/utf8, Variant_name/binary>>/binary, "("/utf8>>/binary, (prepend_default_status(Expr, Status_code))/binary>>/binary, "))"/utf8>> ), oaspec@internal@util@string_extra:indent(_pipe@3, 2, <<"}"/utf8>>); {some, {headers_record, _, Expr@1}} -> _pipe@4 = Sb, oaspec@internal@util@string_extra:indent( _pipe@4, 2, <<<<<<<<<<(status_branch_pattern(Status_code))/binary, " -> Ok("/utf8>>/binary, Variant_name/binary>>/binary, "("/utf8>>/binary, (prepend_default_status(Expr@1, Status_code))/binary>>/binary, "))"/utf8>> ); none -> _pipe@5 = Sb, oaspec@internal@util@string_extra:indent( _pipe@5, 2, <<<<<<<<(status_branch_pattern(Status_code))/binary, " -> Ok("/utf8>>/binary, Variant_name/binary>>/binary, (case Status_code of default_status -> <<"(status)"/utf8>>; _ -> <<""/utf8>> end)/binary>>/binary, ")"/utf8>> ) end. -file("src/oaspec/internal/codegen/client_response.gleam", 234). ?DOC(false). -spec append_headers_arg(binary(), gleam@option:option(headers_record())) -> binary(). append_headers_arg(Body_arg, Headers) -> case Headers of {some, {headers_record, _, Expr}} -> <<<>/binary, Expr/binary>>; none -> Body_arg end. -file("src/oaspec/internal/codegen/client_response.gleam", 138). ?DOC(false). -spec body_branch( gleam@string_tree:string_tree(), oaspec@internal@util@http:http_status_code(), binary(), binary(), gleam@option:option(headers_record()), fun((gleam@string_tree:string_tree()) -> gleam@string_tree:string_tree()) ) -> gleam@string_tree:string_tree(). body_branch(Sb, Status_code, Variant_name, Body_arg, Headers, Extract_body) -> _pipe = Sb, _pipe@1 = oaspec@internal@util@string_extra:indent( _pipe, 2, <<(status_branch_pattern(Status_code))/binary, " -> {"/utf8>> ), _pipe@2 = Extract_body(_pipe@1), _pipe@3 = emit_pre_statements(_pipe@2, Headers), _pipe@4 = oaspec@internal@util@string_extra:indent( _pipe@3, 3, <<<<<<<<"Ok("/utf8, Variant_name/binary>>/binary, "("/utf8>>/binary, (prepend_default_status( append_headers_arg(Body_arg, Headers), Status_code ))/binary>>/binary, "))"/utf8>> ), oaspec@internal@util@string_extra:indent(_pipe@4, 2, <<"}"/utf8>>). -file("src/oaspec/internal/codegen/client_response.gleam", 249). ?DOC(false). -spec generate_empty_content_response( gleam@string_tree:string_tree(), oaspec@internal@util@http:http_status_code(), binary(), gleam@option:option(headers_record()) ) -> gleam@string_tree:string_tree(). generate_empty_content_response(Sb, Status_code, Variant_name, Headers) -> empty_body_branch(Sb, Status_code, Variant_name, Headers). -file("src/oaspec/internal/codegen/client_response.gleam", 261). ?DOC(false). -spec generate_multi_content_response( gleam@string_tree:string_tree(), oaspec@internal@util@http:http_status_code(), binary(), list({binary(), oaspec@internal@openapi@spec:media_type()}), binary(), oaspec@internal@codegen@context:context(), gleam@option:option(headers_record()) ) -> gleam@string_tree:string_tree(). generate_multi_content_response(Sb, Status_code, Variant_name, _, _, _, Headers) -> body_branch( Sb, Status_code, Variant_name, <<"text"/utf8>>, Headers, fun(Sb@1) -> oaspec@internal@util@string_extra:indent( Sb@1, 3, <<"use text <- result.try(text_body(resp.body))"/utf8>> ) end ). -file("src/oaspec/internal/codegen/client_response.gleam", 369). ?DOC(false). -spec response_header_unsupported(binary(), binary()) -> binary(). response_header_unsupported(Header_name, Kind) -> <<<<<<<<<<<<"Cannot generate client extractor for response header '"/utf8, Header_name/binary>>/binary, "' (unsupported schema: "/utf8>>/binary, Kind/binary>>/binary, "). Supported shapes today are inline String / Int / Float / Bool. "/utf8>>/binary, "File a follow-up to oaspec issue #387 if you need typed extraction "/utf8>>/binary, "for this header."/utf8>>. -file("src/oaspec/internal/codegen/client_response.gleam", 341). ?DOC(false). -spec classify_header_schema( gleam@option:option(oaspec@internal@openapi@schema:schema_ref()), binary() ) -> header_field_type(). classify_header_schema(Schema_opt, Header_name) -> case Schema_opt of none -> string_header; {some, {inline, {string_schema, _, _, _, _, _, _}}} -> string_header; {some, {inline, {integer_schema, _, _, _, _, _, _, _}}} -> int_header; {some, {inline, {number_schema, _, _, _, _, _, _, _}}} -> float_header; {some, {inline, {boolean_schema, _}}} -> bool_header; {some, {reference, _, Name}} -> erlang:error(#{gleam_error => panic, message => response_header_unsupported( Header_name, <<<<"$ref to component schema '"/utf8, Name/binary>>/binary, "'"/utf8>> ), file => <>, module => <<"oaspec/internal/codegen/client_response"/utf8>>, function => <<"classify_header_schema"/utf8>>, line => 352}); {some, {inline, {object_schema, _, _, _, _, _, _}}} -> erlang:error(#{gleam_error => panic, message => response_header_unsupported( Header_name, <<"inline object schema"/utf8>> ), file => <>, module => <<"oaspec/internal/codegen/client_response"/utf8>>, function => <<"classify_header_schema"/utf8>>, line => 357}); {some, {inline, {array_schema, _, _, _, _, _}}} -> erlang:error(#{gleam_error => panic, message => response_header_unsupported( Header_name, <<"inline array schema"/utf8>> ), file => <>, module => <<"oaspec/internal/codegen/client_response"/utf8>>, function => <<"classify_header_schema"/utf8>>, line => 359}); {some, {inline, {all_of_schema, _, _}}} -> erlang:error(#{gleam_error => panic, message => response_header_unsupported( Header_name, <<"allOf composition"/utf8>> ), file => <>, module => <<"oaspec/internal/codegen/client_response"/utf8>>, function => <<"classify_header_schema"/utf8>>, line => 361}); {some, {inline, {one_of_schema, _, _, _}}} -> erlang:error(#{gleam_error => panic, message => response_header_unsupported( Header_name, <<"oneOf composition"/utf8>> ), file => <>, module => <<"oaspec/internal/codegen/client_response"/utf8>>, function => <<"classify_header_schema"/utf8>>, line => 363}); {some, {inline, {any_of_schema, _, _, _}}} -> erlang:error(#{gleam_error => panic, message => response_header_unsupported( Header_name, <<"anyOf composition"/utf8>> ), file => <>, module => <<"oaspec/internal/codegen/client_response"/utf8>>, function => <<"classify_header_schema"/utf8>>, line => 365}) end. -file("src/oaspec/internal/codegen/client_response.gleam", 446). ?DOC(false). -spec missing_required_error(binary(), binary()) -> binary(). missing_required_error(Header_name, Kind) -> <<<<<<<<"InvalidResponse(detail: \"missing or invalid required "/utf8, Kind/binary>>/binary, " header: "/utf8>>/binary, Header_name/binary>>/binary, "\")"/utf8>>. -file("src/oaspec/internal/codegen/client_response.gleam", 454). ?DOC(false). -spec missing_required_error_inner(binary(), binary()) -> binary(). missing_required_error_inner(Header_name, Kind) -> <<<<<<<<"InvalidResponse(detail: \"missing or invalid required "/utf8, Kind/binary>>/binary, " header: "/utf8>>/binary, Header_name/binary>>/binary, "\")"/utf8>>. -file("src/oaspec/internal/codegen/client_response.gleam", 465). ?DOC(false). -spec header_lookup_expr(binary()) -> binary(). header_lookup_expr(Header_name) -> <<<<"list.key_find(resp.headers, \""/utf8, (string:lowercase(Header_name))/binary>>/binary, "\")"/utf8>>. -file("src/oaspec/internal/codegen/client_response.gleam", 379). ?DOC(false). -spec header_field_extraction( binary(), binary(), oaspec@internal@openapi@spec:header() ) -> binary(). header_field_extraction(Field_name, Header_name, Header) -> Lookup = header_lookup_expr(Header_name), Kind = classify_header_schema(erlang:element(4, Header), Header_name), case {erlang:element(3, Header), Kind} of {false, string_header} -> <<<<<<<<"let "/utf8, Field_name/binary>>/binary, " = "/utf8>>/binary, Lookup/binary>>/binary, " |> result.map(Some) |> result.unwrap(None)"/utf8>>; {true, string_header} -> <<<<<<<<<<<<"use "/utf8, Field_name/binary>>/binary, " <- result.try("/utf8>>/binary, Lookup/binary>>/binary, " |> result.map_error(fn(_) { "/utf8>>/binary, (missing_required_error(Header_name, <<"string"/utf8>>))/binary>>/binary, " }))"/utf8>>; {false, int_header} -> <<<<<<<<"let "/utf8, Field_name/binary>>/binary, " = "/utf8>>/binary, Lookup/binary>>/binary, " |> result.try(int.parse) |> result.map(Some) |> result.unwrap(None)"/utf8>>; {true, int_header} -> <<<<<<<<<<<<"use "/utf8, Field_name/binary>>/binary, " <- result.try("/utf8>>/binary, Lookup/binary>>/binary, " |> result.try(int.parse) |> result.map_error(fn(_) { "/utf8>>/binary, (missing_required_error(Header_name, <<"integer"/utf8>>))/binary>>/binary, " }))"/utf8>>; {false, float_header} -> <<<<<<<<"let "/utf8, Field_name/binary>>/binary, " = "/utf8>>/binary, Lookup/binary>>/binary, " |> result.try(float.parse) |> result.map(Some) |> result.unwrap(None)"/utf8>>; {true, float_header} -> <<<<<<<<<<<<"use "/utf8, Field_name/binary>>/binary, " <- result.try("/utf8>>/binary, Lookup/binary>>/binary, " |> result.try(float.parse) |> result.map_error(fn(_) { "/utf8>>/binary, (missing_required_error(Header_name, <<"number"/utf8>>))/binary>>/binary, " }))"/utf8>>; {false, bool_header} -> <<<<<<<<"let "/utf8, Field_name/binary>>/binary, " = case "/utf8>>/binary, Lookup/binary>>/binary, " { Ok(\"true\") -> Some(True) Ok(\"false\") -> Some(False) _ -> None }"/utf8>>; {true, bool_header} -> <<<<<<<<<<<<"use "/utf8, Field_name/binary>>/binary, " <- result.try(case "/utf8>>/binary, Lookup/binary>>/binary, " { Ok(\"true\") -> Ok(True) Ok(\"false\") -> Ok(False) _ -> Error("/utf8>>/binary, (missing_required_error_inner( Header_name, <<"boolean"/utf8>> ))/binary>>/binary, ") })"/utf8>> end. -file("src/oaspec/internal/codegen/client_response.gleam", 294). ?DOC(false). -spec build_headers_record( binary(), oaspec@internal@util@http:http_status_code(), oaspec@internal@openapi@spec:response(oaspec@internal@openapi@spec:resolved()) ) -> gleam@option:option(headers_record()). build_headers_record(Op_id, Status_code, Response) -> Headers = begin _pipe = erlang:element(4, Response), _pipe@1 = maps:to_list(_pipe), gleam@list:sort( _pipe@1, fun(A, B) -> gleam@string:compare(erlang:element(1, A), erlang:element(1, B)) end ) end, case Headers of [] -> none; _ -> Record_name = <<<<<<<<"response_types."/utf8, (oaspec@internal@util@naming:schema_to_type_name( Op_id ))/binary>>/binary, "Response"/utf8>>/binary, (oaspec@internal@util@http:status_code_suffix(Status_code))/binary>>/binary, "Headers"/utf8>>, Fields = gleam@list:map( Headers, fun(Entry) -> {Header_name, Header} = Entry, Field_name = oaspec@internal@util@naming:to_snake_case( Header_name ), Pre_statement = header_field_extraction( Field_name, Header_name, Header ), {Field_name, Pre_statement} end ), Pre_statements = gleam@list:map( Fields, fun(P) -> erlang:element(2, P) end ), Assignments = gleam@list:map( Fields, fun(P@1) -> <<<<(erlang:element(1, P@1))/binary, ": "/utf8>>/binary, (erlang:element(1, P@1))/binary>> end ), {some, {headers_record, Pre_statements, <<<<<>/binary, (gleam@string:join(Assignments, <<", "/utf8>>))/binary>>/binary, ")"/utf8>>}} end. -file("src/oaspec/internal/codegen/client_response.gleam", 523). ?DOC(false). -spec inline_schema_to_decoder(oaspec@internal@openapi@schema:schema_object()) -> binary(). inline_schema_to_decoder(S) -> case S of {string_schema, _, _, _, _, _, _} -> <<"dyn_decode.string"/utf8>>; {integer_schema, _, _, _, _, _, _, _} -> <<"dyn_decode.int"/utf8>>; {number_schema, _, _, _, _, _, _, _} -> <<"dyn_decode.float"/utf8>>; {boolean_schema, _} -> <<"dyn_decode.bool"/utf8>>; _ -> <<"dyn_decode.string"/utf8>> end. -file("src/oaspec/internal/codegen/client_response.gleam", 475). ?DOC(false). -spec get_response_decode_expr( oaspec@internal@openapi@schema:schema_ref(), binary(), oaspec@internal@util@http:http_status_code(), oaspec@internal@codegen@context:context() ) -> binary(). get_response_decode_expr(Schema_ref, Op_id, Status_code, _) -> case Schema_ref of {reference, _, Name} -> <<<<"decode.decode_"/utf8, (oaspec@internal@util@naming:to_snake_case(Name))/binary>>/binary, "(text)"/utf8>>; {inline, {array_schema, _, Items, _, _, _}} -> case Items of {reference, _, Name@1} -> <<<<"json.parse(text, dyn_decode.list(decode."/utf8, (oaspec@internal@util@naming:to_snake_case(Name@1))/binary>>/binary, "_decoder()))"/utf8>>; {inline, Inner} -> Inner_decoder = inline_schema_to_decoder(Inner), <<<<"json.parse(text, decode.list("/utf8, Inner_decoder/binary>>/binary, "))"/utf8>> end; {inline, {string_schema, _, _, _, _, _, _}} -> <<"json.parse(text, dyn_decode.string)"/utf8>>; {inline, {integer_schema, _, _, _, _, _, _, _}} -> <<"json.parse(text, dyn_decode.int)"/utf8>>; {inline, {number_schema, _, _, _, _, _, _, _}} -> <<"json.parse(text, dyn_decode.float)"/utf8>>; {inline, {boolean_schema, _}} -> <<"json.parse(text, dyn_decode.bool)"/utf8>>; {inline, _} -> Fn_name = <<<<<<"decode_"/utf8, (oaspec@internal@util@naming:to_snake_case(Op_id))/binary>>/binary, "_response_"/utf8>>/binary, (oaspec@internal@util@naming:to_snake_case( oaspec@internal@util@http:status_code_suffix(Status_code) ))/binary>>, <<<<"decode."/utf8, Fn_name/binary>>/binary, "(text)"/utf8>> end. -file("src/oaspec/internal/codegen/client_response.gleam", 69). ?DOC(false). -spec generate_single_content_response( gleam@string_tree:string_tree(), oaspec@internal@util@http:http_status_code(), binary(), binary(), oaspec@internal@openapi@spec:media_type(), binary(), oaspec@internal@codegen@context:context(), gleam@option:option(headers_record()) ) -> gleam@string_tree:string_tree(). generate_single_content_response( Sb, Status_code, Variant_name, Media_type_name, Media_type, Op_id, Ctx, Headers ) -> case oaspec@internal@util@content_type:from_string(Media_type_name) of application_octet_stream -> case erlang:element(2, Media_type) of {some, _} -> body_branch( Sb, Status_code, Variant_name, <<"bytes"/utf8>>, Headers, fun(Sb@1) -> oaspec@internal@util@string_extra:indent( Sb@1, 3, <<"use bytes <- result.try(bytes_body(resp.body))"/utf8>> ) end ); _ -> empty_body_branch(Sb, Status_code, Variant_name, Headers) end; text_plain -> case erlang:element(2, Media_type) of {some, _} -> body_branch( Sb, Status_code, Variant_name, <<"text"/utf8>>, Headers, fun(Sb@2) -> oaspec@internal@util@string_extra:indent( Sb@2, 3, <<"use text <- result.try(text_body(resp.body))"/utf8>> ) end ); _ -> empty_body_branch(Sb, Status_code, Variant_name, Headers) end; application_xml -> case erlang:element(2, Media_type) of {some, _} -> body_branch( Sb, Status_code, Variant_name, <<"text"/utf8>>, Headers, fun(Sb@2) -> oaspec@internal@util@string_extra:indent( Sb@2, 3, <<"use text <- result.try(text_body(resp.body))"/utf8>> ) end ); _ -> empty_body_branch(Sb, Status_code, Variant_name, Headers) end; text_xml -> case erlang:element(2, Media_type) of {some, _} -> body_branch( Sb, Status_code, Variant_name, <<"text"/utf8>>, Headers, fun(Sb@2) -> oaspec@internal@util@string_extra:indent( Sb@2, 3, <<"use text <- result.try(text_body(resp.body))"/utf8>> ) end ); _ -> empty_body_branch(Sb, Status_code, Variant_name, Headers) end; _ -> case erlang:element(2, Media_type) of {some, Schema_ref} -> Decode_expr = get_response_decode_expr( Schema_ref, Op_id, Status_code, Ctx ), Sb@3 = begin _pipe = Sb, _pipe@1 = oaspec@internal@util@string_extra:indent( _pipe, 2, <<(status_branch_pattern(Status_code))/binary, " -> {"/utf8>> ), _pipe@2 = oaspec@internal@util@string_extra:indent( _pipe@1, 3, <<"use text <- result.try(text_body(resp.body))"/utf8>> ), emit_pre_statements(_pipe@2, Headers) end, _pipe@3 = Sb@3, _pipe@4 = oaspec@internal@util@string_extra:indent( _pipe@3, 3, <<<<"case "/utf8, Decode_expr/binary>>/binary, " {"/utf8>> ), _pipe@5 = oaspec@internal@util@string_extra:indent( _pipe@4, 4, <<<<<<<<"Ok(decoded) -> Ok("/utf8, Variant_name/binary>>/binary, "("/utf8>>/binary, (prepend_default_status( append_headers_arg( <<"decoded"/utf8>>, Headers ), Status_code ))/binary>>/binary, "))"/utf8>> ), _pipe@6 = oaspec@internal@util@string_extra:indent( _pipe@5, 4, <<"Error(_) -> Error(DecodeFailure(detail: \"Failed to decode response body\"))"/utf8>> ), _pipe@7 = oaspec@internal@util@string_extra:indent( _pipe@6, 3, <<"}"/utf8>> ), oaspec@internal@util@string_extra:indent( _pipe@7, 2, <<"}"/utf8>> ); _ -> empty_body_branch(Sb, Status_code, Variant_name, Headers) end end.