-module(nori@codegen@ir_builder). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/nori/codegen/ir_builder.gleam"). -export([build/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. ?MODULEDOC( " Transforms an OpenAPI Document into a language-agnostic CodegenIR.\n" "\n" " This is the bridge between the parsed OpenAPI spec and code generators.\n" ). -file("src/nori/codegen/ir_builder.gleam", 45). -spec extract_base_url(nori@document:document()) -> gleam@option:option(binary()). extract_base_url(Doc) -> case erlang:element(5, Doc) of [First | _] -> {some, erlang:element(2, First)}; [] -> none end. -file("src/nori/codegen/ir_builder.gleam", 290). -spec string_format_to_typeref(gleam@option:option(binary())) -> nori@codegen@ir:type_ref(). string_format_to_typeref(Format) -> case Format of {some, <<"date-time"/utf8>>} -> {primitive, p_date_time}; {some, <<"date"/utf8>>} -> {primitive, p_date}; {some, <<"binary"/utf8>>} -> {primitive, p_binary}; _ -> {primitive, p_string} end. -file("src/nori/codegen/ir_builder.gleam", 306). -spec ref_to_typeref(binary()) -> nori@codegen@ir:type_ref(). ref_to_typeref(Ref_str) -> case gleam@string:split(Ref_str, <<"/"/utf8>>) of [_, _, _, Name] -> {named, Name}; _ -> {named, Ref_str} end. -file("src/nori/codegen/ir_builder.gleam", 383). -spec parse_http_method(binary()) -> gleam@option:option(nori@codegen@ir:http_method()). parse_http_method(Method) -> case Method of <<"get"/utf8>> -> {some, get}; <<"post"/utf8>> -> {some, post}; <<"put"/utf8>> -> {some, put}; <<"delete"/utf8>> -> {some, delete}; <<"patch"/utf8>> -> {some, patch}; <<"head"/utf8>> -> {some, head}; <<"options"/utf8>> -> {some, options}; _ -> none end. -file("src/nori/codegen/ir_builder.gleam", 396). -spec method_to_string(nori@codegen@ir:http_method()) -> binary(). method_to_string(Method) -> case Method of get -> <<"get"/utf8>>; post -> <<"post"/utf8>>; put -> <<"put"/utf8>>; delete -> <<"delete"/utf8>>; patch -> <<"patch"/utf8>>; head -> <<"head"/utf8>>; options -> <<"options"/utf8>> end. -file("src/nori/codegen/ir_builder.gleam", 442). -spec param_location_to_ir(nori@parameter:parameter_location()) -> nori@codegen@ir:param_location(). param_location_to_ir(Loc) -> case Loc of in_path -> path_param; in_query -> query_param; in_header -> header_param; in_cookie -> cookie_param end. -file("src/nori/codegen/ir_builder.gleam", 603). -spec api_key_location_to_ir(nori@security:api_key_location()) -> nori@codegen@ir:api_key_location_i_r(). api_key_location_to_ir(Loc) -> case Loc of in_header -> in_header; in_query -> in_query; in_cookie -> in_cookie end. -file("src/nori/codegen/ir_builder.gleam", 581). -spec security_scheme_to_ir(binary(), nori@security:security_scheme()) -> nori@codegen@ir:security_scheme_i_r(). security_scheme_to_ir(Name, Scheme) -> case Scheme of {http_security_scheme, <<"bearer"/utf8>>, Fmt, _, _} -> {bearer_auth, Name, Fmt}; {http_security_scheme, <<"basic"/utf8>>, _, _, _} -> {basic_auth, Name}; {http_security_scheme, _, _, _, _} -> {basic_auth, Name}; {api_key_security_scheme, Param_name, Loc, _, _} -> {api_key_auth, Name, Param_name, api_key_location_to_ir(Loc)}; {o_auth2_security_scheme, _, _, _} -> {o_auth2_auth, Name}; {open_id_connect_security_scheme, Url, _, _} -> {open_id_connect_auth, Name, Url}; {mutual_tls_security_scheme, _, _} -> {o_auth2_auth, Name} end. -file("src/nori/codegen/ir_builder.gleam", 565). -spec build_security_schemes(nori@document:document()) -> list(nori@codegen@ir:security_scheme_i_r()). build_security_schemes(Doc) -> case erlang:element(8, Doc) of none -> []; {some, Components} -> _pipe = maps:to_list(erlang:element(8, Components)), gleam@list:filter_map( _pipe, fun(Pair) -> {Name, Ref_scheme} = Pair, case Ref_scheme of {reference, _} -> {error, nil}; {inline, Scheme} -> {ok, security_scheme_to_ir(Name, Scheme)} end end ) end. -file("src/nori/codegen/ir_builder.gleam", 611). -spec build_security_requirements( list(gleam@dict:dict(binary(), list(binary()))) ) -> list(nori@codegen@ir:security_requirement_i_r()). build_security_requirements(Reqs) -> gleam@list:flat_map(Reqs, fun(Req) -> _pipe = maps:to_list(Req), gleam@list:map( _pipe, fun(Pair) -> {Scheme_name, Scopes} = Pair, {security_requirement_i_r, Scheme_name, Scopes} end ) end). -file("src/nori/codegen/ir_builder.gleam", 629). ?DOC( " Attempt to extract a string from a gleam/json Json value.\n" " Json values from enum_values are opaque; we convert via string representation.\n" ). -spec json_to_string(gleam@json:json()) -> gleam@option:option(binary()). json_to_string(Json_val) -> Str = gleam@json:to_string(Json_val), case gleam_stdlib:string_starts_with(Str, <<"\""/utf8>>) andalso gleam_stdlib:string_ends_with( Str, <<"\""/utf8>> ) of true -> Trimmed = begin _pipe = Str, _pipe@1 = gleam@string:drop_start(_pipe, 1), gleam@string:drop_end(_pipe@1, 1) end, {some, Trimmed}; false -> {some, Str} end. -file("src/nori/codegen/ir_builder.gleam", 299). -spec ref_schema_to_typeref(nori@reference:ref(nori@schema:schema())) -> nori@codegen@ir:type_ref(). ref_schema_to_typeref(Ref_schema) -> case Ref_schema of {reference, Ref_str} -> ref_to_typeref(Ref_str); {inline, S} -> schema_type_to_typeref(S) end. -file("src/nori/codegen/ir_builder.gleam", 218). -spec schema_type_to_typeref(nori@schema:schema()) -> nori@codegen@ir:type_ref(). schema_type_to_typeref(S) -> case erlang:element(7, S) of {some, Ref_str} -> ref_to_typeref(Ref_str); none -> case erlang:element(28, S) of none -> unknown; {some, {single_type, Json_type}} -> json_type_to_typeref(Json_type, S); {some, {multiple_types, Types}} -> multiple_types_to_typeref(Types, S) end end. -file("src/nori/codegen/ir_builder.gleam", 263). -spec multiple_types_to_typeref( list(nori@schema:json_type()), nori@schema:schema() ) -> nori@codegen@ir:type_ref(). multiple_types_to_typeref(Types, S) -> Non_null = gleam@list:filter(Types, fun(T) -> case T of type_null -> false; _ -> true end end), Has_null = gleam@list:any(Types, fun(T@1) -> case T@1 of type_null -> true; _ -> false end end), case {Non_null, Has_null} of {[Single_type], true} -> {nullable, json_type_to_typeref(Single_type, S)}; {[Single_type@1], false} -> json_type_to_typeref(Single_type@1, S); {_, true} -> {nullable, unknown}; {_, false} -> unknown end. -file("src/nori/codegen/ir_builder.gleam", 234). -spec json_type_to_typeref(nori@schema:json_type(), nori@schema:schema()) -> nori@codegen@ir:type_ref(). json_type_to_typeref(Json_type, S) -> case Json_type of type_string -> string_format_to_typeref(erlang:element(48, S)); type_integer -> {primitive, p_int}; type_number -> {primitive, p_float}; type_boolean -> {primitive, p_bool}; type_null -> {primitive, p_unit}; json_type_array -> case erlang:element(20, S) of {some, Items_ref} -> {array, ref_schema_to_typeref(Items_ref)}; none -> {array, unknown} end; type_object -> case erlang:element(24, S) of {some, {additional_properties_schema, Val_ref}} -> {dict, {primitive, p_string}, ref_schema_to_typeref(Val_ref)}; _ -> case gleam@dict:is_empty(erlang:element(22, S)) of true -> unknown; false -> unknown end end end. -file("src/nori/codegen/ir_builder.gleam", 116). -spec build_record_type(binary(), nori@schema:schema()) -> nori@codegen@ir:type_def(). build_record_type(Name, S) -> Fields = begin _pipe = maps:to_list(erlang:element(22, S)), gleam@list:map( _pipe, fun(Pair) -> {Field_name, Ref_schema} = Pair, Is_required = gleam@list:contains( erlang:element(46, S), Field_name ), {Type_ref, Description, Read_only, Write_only} = case Ref_schema of {reference, Ref_str} -> {ref_to_typeref(Ref_str), none, false, false}; {inline, Field_schema} -> Tr = schema_type_to_typeref(Field_schema), Ro = gleam@option:unwrap( erlang:element(56, Field_schema), false ), Wo = gleam@option:unwrap( erlang:element(57, Field_schema), false ), {Tr, erlang:element(53, Field_schema), Ro, Wo} end, {field, Field_name, Type_ref, Is_required, Description, Read_only, Write_only} end ) end, {record_type, Name, Fields, erlang:element(53, S)}. -file("src/nori/codegen/ir_builder.gleam", 148). -spec build_all_of_type(binary(), nori@schema:schema()) -> nori@codegen@ir:type_def(). build_all_of_type(Name, S) -> Fields = gleam@list:flat_map( erlang:element(11, S), fun(Ref_schema) -> case Ref_schema of {reference, _} -> []; {inline, Sub_schema} -> _pipe = maps:to_list(erlang:element(22, Sub_schema)), gleam@list:map( _pipe, fun(Pair) -> {Field_name, Prop_ref} = Pair, Is_required = gleam@list:contains( erlang:element(46, Sub_schema), Field_name ), {Type_ref, Description, Read_only, Write_only} = case Prop_ref of {reference, Ref_str} -> {ref_to_typeref(Ref_str), none, false, false}; {inline, Field_schema} -> Tr = schema_type_to_typeref(Field_schema), Ro = gleam@option:unwrap( erlang:element(56, Field_schema), false ), Wo = gleam@option:unwrap( erlang:element(57, Field_schema), false ), {Tr, erlang:element(53, Field_schema), Ro, Wo} end, {field, Field_name, Type_ref, Is_required, Description, Read_only, Write_only} end ) end end ), {record_type, Name, Fields, erlang:element(53, S)}. -file("src/nori/codegen/ir_builder.gleam", 189). -spec build_union_type( binary(), list(nori@reference:ref(nori@schema:schema())), gleam@option:option(nori@schema:discriminator()), gleam@option:option(binary()) ) -> nori@codegen@ir:type_def(). build_union_type(Name, Members, Discriminator, Description) -> Member_refs = gleam@list:map(Members, fun(Ref_schema) -> case Ref_schema of {reference, Ref_str} -> ref_to_typeref(Ref_str); {inline, Sub_schema} -> schema_type_to_typeref(Sub_schema) end end), Disc = case Discriminator of {some, D} -> {some, erlang:element(2, D)}; none -> none end, {union_type, Name, Member_refs, Disc, Description}. -file("src/nori/codegen/ir_builder.gleam", 69). -spec schema_to_typedef(binary(), nori@schema:schema()) -> nori@codegen@ir:type_def(). schema_to_typedef(Name, S) -> case erlang:element(30, S) of {some, Values} -> Variants = gleam@list:filter_map( Values, fun(Json_val) -> case json_to_string(Json_val) of {some, Str} -> {ok, {enum_variant, Str, Str}}; none -> {error, nil} end end ), {enum_type, Name, Variants, erlang:element(53, S)}; none -> case erlang:element(11, S) of [_ | _] -> build_all_of_type(Name, S); [] -> case {erlang:element(13, S), erlang:element(12, S)} of {[_ | _], _} -> build_union_type( Name, erlang:element(13, S), erlang:element(59, S), erlang:element(53, S) ); {_, [_ | _]} -> build_union_type( Name, erlang:element(12, S), erlang:element(59, S), erlang:element(53, S) ); {_, _} -> case gleam@dict:is_empty(erlang:element(22, S)) of false -> build_record_type(Name, S); true -> Target = schema_type_to_typeref(S), {alias_type, Name, Target, erlang:element(53, S)} end end end end. -file("src/nori/codegen/ir_builder.gleam", 56). -spec build_types(nori@document:document()) -> list(nori@codegen@ir:type_def()). build_types(Doc) -> case erlang:element(8, Doc) of none -> []; {some, Components} -> _pipe = maps:to_list(erlang:element(2, Components)), gleam@list:map( _pipe, fun(Pair) -> {Name, Schema} = Pair, schema_to_typedef(Name, Schema) end ) end. -file("src/nori/codegen/ir_builder.gleam", 425). -spec build_param(nori@parameter:parameter()) -> nori@codegen@ir:endpoint_param(). build_param(Param) -> Location = param_location_to_ir(erlang:element(3, Param)), Type_ref = case erlang:element(11, Param) of {some, Ref_schema} -> ref_schema_to_typeref(Ref_schema); none -> unknown end, Required = gleam@option:unwrap(erlang:element(5, Param), false), {endpoint_param, erlang:element(2, Param), Location, Type_ref, Required, erlang:element(4, Param)}. -file("src/nori/codegen/ir_builder.gleam", 412). -spec build_params( list(nori@reference:ref(nori@parameter:parameter())), list(nori@reference:ref(nori@parameter:parameter())) ) -> list(nori@codegen@ir:endpoint_param()). build_params(Path_level, Op_level) -> All_params = lists:append(Path_level, Op_level), gleam@list:filter_map(All_params, fun(Ref_param) -> case Ref_param of {reference, _} -> {error, nil}; {inline, Param} -> {ok, build_param(Param)} end end). -file("src/nori/codegen/ir_builder.gleam", 455). -spec build_request_body( gleam@option:option(nori@reference:ref(nori@request_body:request_body())) ) -> gleam@option:option(nori@codegen@ir:request_body_i_r()). build_request_body(Body) -> case Body of none -> none; {some, {reference, _}} -> none; {some, {inline, Rb}} -> Content_type = <<"application/json"/utf8>>, case gleam_stdlib:map_get(erlang:element(3, Rb), Content_type) of {ok, Media_type} -> Type_ref = case erlang:element(2, Media_type) of {some, Ref_schema} -> ref_schema_to_typeref(Ref_schema); none -> unknown end, Required = gleam@option:unwrap(erlang:element(4, Rb), false), {some, {request_body_i_r, Content_type, Type_ref, Required}}; {error, _} -> case maps:to_list(erlang:element(3, Rb)) of [{Ct, Media_type@1} | _] -> Type_ref@1 = case erlang:element(2, Media_type@1) of {some, Ref_schema@1} -> ref_schema_to_typeref(Ref_schema@1); none -> unknown end, Required@1 = gleam@option:unwrap( erlang:element(4, Rb), false ), {some, {request_body_i_r, Ct, Type_ref@1, Required@1}}; [] -> none end end end. -file("src/nori/codegen/ir_builder.gleam", 517). -spec build_response(binary(), nori@response:response()) -> nori@codegen@ir:response_i_r(). build_response(Status_code, Resp) -> case gleam_stdlib:map_get( erlang:element(4, Resp), <<"application/json"/utf8>> ) of {ok, Media_type} -> Type_ref = case erlang:element(2, Media_type) of {some, Ref_schema} -> {some, ref_schema_to_typeref(Ref_schema)}; none -> none end, {response_i_r, Status_code, erlang:element(2, Resp), {some, <<"application/json"/utf8>>}, Type_ref}; {error, _} -> case maps:to_list(erlang:element(4, Resp)) of [{Ct, Media_type@1} | _] -> Type_ref@1 = case erlang:element(2, Media_type@1) of {some, Ref_schema@1} -> {some, ref_schema_to_typeref(Ref_schema@1)}; none -> none end, {response_i_r, Status_code, erlang:element(2, Resp), {some, Ct}, Type_ref@1}; [] -> {response_i_r, Status_code, erlang:element(2, Resp), none, none} end end. -file("src/nori/codegen/ir_builder.gleam", 504). -spec build_responses( gleam@dict:dict(binary(), nori@reference:ref(nori@response:response())) ) -> list(nori@codegen@ir:response_i_r()). build_responses(Responses) -> _pipe = maps:to_list(Responses), gleam@list:filter_map( _pipe, fun(Pair) -> {Status_code, Ref_response} = Pair, case Ref_response of {reference, _} -> {error, nil}; {inline, Resp} -> {ok, build_response(Status_code, Resp)} end end ). -file("src/nori/codegen/ir_builder.gleam", 351). -spec build_endpoint( binary(), nori@codegen@ir:http_method(), nori@operation:operation(), list(nori@reference:ref(nori@parameter:parameter())) ) -> nori@codegen@ir:endpoint(). build_endpoint(Path, Method, Op, Path_level_params) -> Operation_id = gleam@option:unwrap( erlang:element(6, Op), <<<<(method_to_string(Method))/binary, "_"/utf8>>/binary, Path/binary>> ), Params = build_params(Path_level_params, erlang:element(7, Op)), Request_body = build_request_body(erlang:element(8, Op)), Responses = build_responses(erlang:element(9, Op)), Deprecated = gleam@option:unwrap(erlang:element(11, Op), false), Endpoint_security = case erlang:element(12, Op) of none -> none; {some, Reqs} -> {some, build_security_requirements(Reqs)} end, {endpoint, Operation_id, Method, Path, erlang:element(3, Op), erlang:element(4, Op), erlang:element(2, Op), Params, Request_body, Responses, Deprecated, Endpoint_security}. -file("src/nori/codegen/ir_builder.gleam", 335). -spec build_endpoints_from_path_item(binary(), nori@operation:path_item()) -> list(nori@codegen@ir:endpoint()). build_endpoints_from_path_item(Path, Item) -> Path_level_params = erlang:element(14, Item), _pipe = nori@paths:get_operations(Item), gleam@list:filter_map( _pipe, fun(Pair) -> {Method_str, Op} = Pair, case parse_http_method(Method_str) of {some, Method} -> {ok, build_endpoint(Path, Method, Op, Path_level_params)}; none -> {error, nil} end end ). -file("src/nori/codegen/ir_builder.gleam", 318). -spec build_endpoints(nori@document:document()) -> list(nori@codegen@ir:endpoint()). build_endpoints(Doc) -> case erlang:element(6, Doc) of none -> []; {some, Paths_dict} -> _pipe = maps:to_list(Paths_dict), gleam@list:flat_map( _pipe, fun(Pair) -> {Path, Path_item_ref} = Pair, case Path_item_ref of {reference, _} -> []; {inline, Path_item} -> build_endpoints_from_path_item(Path, Path_item) end end ) end. -file("src/nori/codegen/ir_builder.gleam", 22). ?DOC(" Builds a CodegenIR from a parsed OpenAPI Document.\n"). -spec build(nori@document:document()) -> nori@codegen@ir:codegen_i_r(). build(Doc) -> Types = build_types(Doc), Endpoints = build_endpoints(Doc), Base_url = extract_base_url(Doc), Security_schemes = build_security_schemes(Doc), Global_security = build_security_requirements(erlang:element(9, Doc)), {codegen_i_r, erlang:element(2, erlang:element(3, Doc)), erlang:element(7, erlang:element(3, Doc)), Base_url, Types, Endpoints, Security_schemes, Global_security}.