-module(oaspec@openapi@resolve). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/oaspec/openapi/resolve.gleam"). -export([resolve/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/openapi/resolve.gleam", 126). ?DOC(" Extract the last segment of a $ref path.\n"). -spec extract_ref_name(binary()) -> binary(). extract_ref_name(Ref) -> _pipe = Ref, _pipe@1 = gleam@string:split(_pipe, <<"/"/utf8>>), _pipe@2 = gleam@list:last(_pipe@1), gleam@result:unwrap(_pipe@2, <<"unknown"/utf8>>). -file("src/oaspec/openapi/resolve.gleam", 93). ?DOC(" Follow a $ref chain to find the concrete value.\n"). -spec resolve_alias( gleam@dict:dict(binary(), oaspec@openapi@spec:ref_or(RWR)), binary(), binary(), gleam@set:set(binary()) ) -> {ok, RWR} | {error, oaspec@openapi@parser:parse_error()}. resolve_alias(Entries, Ref, Context, Seen) -> case gleam@set:contains(Seen, Ref) of true -> {error, {invalid_value, Context, <<"Circular component alias detected: "/utf8, Ref/binary>>}}; false -> New_seen = gleam@set:insert(Seen, Ref), Ref_name = extract_ref_name(Ref), case gleam_stdlib:map_get(Entries, Ref_name) of {ok, {value, Value}} -> {ok, Value}; {ok, {ref, Next_ref}} -> resolve_alias(Entries, Next_ref, Context, New_seen); {error, _} -> {error, {invalid_value, Context, <<<<<<<<"Unresolved component alias: "/utf8, Ref/binary>>/binary, " — target '"/utf8>>/binary, Ref_name/binary>>/binary, "' not found."/utf8>>}} end end. -file("src/oaspec/openapi/resolve.gleam", 70). ?DOC( " Resolve all aliases in a component dict.\n" " After resolution, all entries are Value.\n" ). -spec resolve_component_dict( gleam@dict:dict(binary(), oaspec@openapi@spec:ref_or(RWI)), binary() ) -> {ok, gleam@dict:dict(binary(), oaspec@openapi@spec:ref_or(RWI))} | {error, oaspec@openapi@parser:parse_error()}. resolve_component_dict(Entries, Context) -> _pipe = maps:to_list(Entries), gleam@list:try_fold( _pipe, Entries, fun(Acc, Entry) -> {Name, Value} = Entry, case Value of {value, _} -> {ok, Acc}; {ref, Ref} -> gleam@result:'try'( resolve_alias( Entries, Ref, <<<>/binary, Name/binary>>, gleam@set:new() ), fun(Resolved) -> {ok, gleam@dict:insert(Acc, Name, {value, Resolved})} end ) end end ). -file("src/oaspec/openapi/resolve.gleam", 219). ?DOC(" Resolve a parameter Ref by looking it up in components.parameters.\n"). -spec resolve_param_ref( oaspec@openapi@spec:ref_or(oaspec@openapi@spec:parameter(oaspec@openapi@spec:spec_stage())), oaspec@openapi@spec:components(oaspec@openapi@spec:spec_stage()) ) -> oaspec@openapi@spec:ref_or(oaspec@openapi@spec:parameter(oaspec@openapi@spec:spec_stage())). resolve_param_ref(Ref_or, Components) -> case Ref_or of {value, _} -> Ref_or; {ref, Ref_str} -> Ref_name = extract_ref_name(Ref_str), case gleam_stdlib:map_get(erlang:element(3, Components), Ref_name) of {ok, {value, P}} -> {value, P}; _ -> Ref_or end end. -file("src/oaspec/openapi/resolve.gleam", 236). ?DOC(" Resolve a request body Ref by looking it up in components.request_bodies.\n"). -spec resolve_request_body_ref( oaspec@openapi@spec:ref_or(oaspec@openapi@spec:request_body(oaspec@openapi@spec:spec_stage())), oaspec@openapi@spec:components(oaspec@openapi@spec:spec_stage()) ) -> oaspec@openapi@spec:ref_or(oaspec@openapi@spec:request_body(oaspec@openapi@spec:spec_stage())). resolve_request_body_ref(Ref_or, Components) -> case Ref_or of {value, _} -> Ref_or; {ref, Ref_str} -> Ref_name = extract_ref_name(Ref_str), case gleam_stdlib:map_get(erlang:element(4, Components), Ref_name) of {ok, {value, Rb}} -> {value, Rb}; _ -> Ref_or end end. -file("src/oaspec/openapi/resolve.gleam", 253). ?DOC(" Resolve a response Ref by looking it up in components.responses.\n"). -spec resolve_response_ref( oaspec@openapi@spec:ref_or(oaspec@openapi@spec:response(oaspec@openapi@spec:spec_stage())), oaspec@openapi@spec:components(oaspec@openapi@spec:spec_stage()) ) -> oaspec@openapi@spec:ref_or(oaspec@openapi@spec:response(oaspec@openapi@spec:spec_stage())). resolve_response_ref(Ref_or, Components) -> case Ref_or of {value, _} -> Ref_or; {ref, Ref_str} -> Ref_name = extract_ref_name(Ref_str), case gleam_stdlib:map_get(erlang:element(5, Components), Ref_name) of {ok, {value, R}} -> {value, R}; _ -> Ref_or end end. -file("src/oaspec/openapi/resolve.gleam", 270). ?DOC(" Map over an Option value.\n"). -spec option_map(gleam@option:option(RYI), fun((RYI) -> RYI)) -> gleam@option:option(RYI). option_map(Opt, F) -> case Opt of {some, V} -> {some, F(V)}; none -> none end. -file("src/oaspec/openapi/resolve.gleam", 204). ?DOC(" Resolve inline refs within a callback.\n"). -spec resolve_inline_callback( oaspec@openapi@spec:callback(oaspec@openapi@spec:spec_stage()), oaspec@openapi@spec:components(oaspec@openapi@spec:spec_stage()) ) -> oaspec@openapi@spec:callback(oaspec@openapi@spec:spec_stage()). resolve_inline_callback(Cb, Components) -> {callback, gleam@dict:map_values( erlang:element(2, Cb), fun(_, Ref_or) -> case Ref_or of {ref, Ref_str} -> resolve_path_item_ref(Ref_str, Components); {value, Pi} -> {value, resolve_inline_path_item(Pi, Components)} end end )}. -file("src/oaspec/openapi/resolve.gleam", 151). ?DOC(" Resolve a path-level $ref by looking it up in components.pathItems.\n"). -spec resolve_path_item_ref( binary(), oaspec@openapi@spec:components(oaspec@openapi@spec:spec_stage()) ) -> oaspec@openapi@spec:ref_or(oaspec@openapi@spec:path_item(oaspec@openapi@spec:spec_stage())). resolve_path_item_ref(Ref_str, Components) -> Ref_name = extract_ref_name(Ref_str), case gleam_stdlib:map_get(erlang:element(7, Components), Ref_name) of {ok, {value, Pi}} -> {value, resolve_inline_path_item(Pi, Components)}; {ok, {ref, _}} -> {ref, Ref_str}; {error, _} -> {ref, Ref_str} end. -file("src/oaspec/openapi/resolve.gleam", 164). ?DOC(" Resolve inline refs within a path item.\n"). -spec resolve_inline_path_item( oaspec@openapi@spec:path_item(oaspec@openapi@spec:spec_stage()), oaspec@openapi@spec:components(oaspec@openapi@spec:spec_stage()) ) -> oaspec@openapi@spec:path_item(oaspec@openapi@spec:spec_stage()). resolve_inline_path_item(Pi, Components) -> {path_item, erlang:element(2, Pi), erlang:element(3, Pi), option_map( erlang:element(4, Pi), fun(_capture) -> resolve_inline_operation(_capture, Components) end ), option_map( erlang:element(5, Pi), fun(_capture@1) -> resolve_inline_operation(_capture@1, Components) end ), option_map( erlang:element(6, Pi), fun(_capture@2) -> resolve_inline_operation(_capture@2, Components) end ), option_map( erlang:element(7, Pi), fun(_capture@3) -> resolve_inline_operation(_capture@3, Components) end ), option_map( erlang:element(8, Pi), fun(_capture@4) -> resolve_inline_operation(_capture@4, Components) end ), option_map( erlang:element(9, Pi), fun(_capture@5) -> resolve_inline_operation(_capture@5, Components) end ), option_map( erlang:element(10, Pi), fun(_capture@6) -> resolve_inline_operation(_capture@6, Components) end ), option_map( erlang:element(11, Pi), fun(_capture@7) -> resolve_inline_operation(_capture@7, Components) end ), gleam@list:map( erlang:element(12, Pi), fun(_capture@8) -> resolve_param_ref(_capture@8, Components) end ), erlang:element(13, Pi)}. -file("src/oaspec/openapi/resolve.gleam", 183). ?DOC(" Resolve inline refs within an operation.\n"). -spec resolve_inline_operation( oaspec@openapi@spec:operation(oaspec@openapi@spec:spec_stage()), oaspec@openapi@spec:components(oaspec@openapi@spec:spec_stage()) ) -> oaspec@openapi@spec:operation(oaspec@openapi@spec:spec_stage()). resolve_inline_operation(Op, Components) -> {operation, erlang:element(2, Op), erlang:element(3, Op), erlang:element(4, Op), erlang:element(5, Op), gleam@list:map( erlang:element(6, Op), fun(_capture) -> resolve_param_ref(_capture, Components) end ), option_map( erlang:element(7, Op), fun(_capture@1) -> resolve_request_body_ref(_capture@1, Components) end ), gleam@dict:map_values( erlang:element(8, Op), fun(_, Ref_or) -> resolve_response_ref(Ref_or, Components) end ), erlang:element(9, Op), erlang:element(10, Op), gleam@dict:map_values( erlang:element(11, Op), fun(_, Cb) -> resolve_inline_callback(Cb, Components) end ), erlang:element(12, Op), erlang:element(13, Op)}. -file("src/oaspec/openapi/resolve.gleam", 138). ?DOC(" Resolve inline refs in a paths dict by looking up components.\n"). -spec resolve_inline_paths( gleam@dict:dict(binary(), oaspec@openapi@spec:ref_or(oaspec@openapi@spec:path_item(oaspec@openapi@spec:spec_stage()))), oaspec@openapi@spec:components(oaspec@openapi@spec:spec_stage()) ) -> gleam@dict:dict(binary(), oaspec@openapi@spec:ref_or(oaspec@openapi@spec:path_item(oaspec@openapi@spec:spec_stage()))). resolve_inline_paths(Paths, Components) -> gleam@dict:map_values(Paths, fun(_, Ref_or) -> case Ref_or of {ref, Ref_str} -> resolve_path_item_ref(Ref_str, Components); {value, Pi} -> {value, resolve_inline_path_item(Pi, Components)} end end). -file("src/oaspec/openapi/resolve.gleam", 17). ?DOC( " Resolve all RefOr aliases in the spec.\n" " Call after parse and normalize, before capability_check and codegen.\n" " Resolves both component-level aliases and inline $ref within operations.\n" ). -spec resolve( oaspec@openapi@spec:open_api_spec(oaspec@openapi@spec:spec_stage()) ) -> {ok, oaspec@openapi@spec:open_api_spec(oaspec@openapi@spec:spec_stage())} | {error, oaspec@openapi@parser:parse_error()}. resolve(Spec) -> case erlang:element(5, Spec) of none -> {ok, Spec}; {some, Components} -> gleam@result:'try'( resolve_component_dict( erlang:element(3, Components), <<"components.parameters"/utf8>> ), fun(Parameters) -> gleam@result:'try'( resolve_component_dict( erlang:element(4, Components), <<"components.requestBodies"/utf8>> ), fun(Request_bodies) -> gleam@result:'try'( resolve_component_dict( erlang:element(5, Components), <<"components.responses"/utf8>> ), fun(Responses) -> gleam@result:'try'( resolve_component_dict( erlang:element(6, Components), <<"components.securitySchemes"/utf8>> ), fun(Security_schemes) -> gleam@result:'try'( resolve_component_dict( erlang:element( 7, Components ), <<"components.pathItems"/utf8>> ), fun(Path_items) -> Resolved_components = {components, erlang:element( 2, Components ), Parameters, Request_bodies, Responses, Security_schemes, Path_items, erlang:element( 8, Components ), erlang:element( 9, Components ), erlang:element( 10, Components )}, Resolved_paths = resolve_inline_paths( erlang:element(4, Spec), Resolved_components ), Resolved_webhooks = resolve_inline_paths( erlang:element(8, Spec), Resolved_components ), {ok, {open_api_spec, erlang:element( 2, Spec ), erlang:element( 3, Spec ), Resolved_paths, {some, Resolved_components}, erlang:element( 6, Spec ), erlang:element( 7, Spec ), Resolved_webhooks, erlang:element( 9, Spec ), erlang:element( 10, Spec ), erlang:element( 11, Spec )}} end ) end ) end ) end ) end ) end.