Current section

Files

Jump to
oaspec src oaspec@openapi@resolve.erl
Raw

src/oaspec@openapi@resolve.erl

-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,
<<<<Context/binary, "."/utf8>>/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.