Current section

Files

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

src/oaspec@openapi@parser.erl

-module(oaspec@openapi@parser).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/oaspec/openapi/parser.gleam").
-export([parse_error_to_string/1, parse_schema_object/2, parse_schema_ref/2, parse_string/1, parse_file/1]).
-export_type([parse_error/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.
-type parse_error() :: {file_error, binary()} |
{yaml_error, binary()} |
{missing_field, binary(), binary()} |
{invalid_value, binary(), binary()}.
-file("src/oaspec/openapi/parser.gleam", 573).
?DOC(
" Validate that a $ref string starts with the expected local prefix\n"
" (e.g. \"#/components/parameters/\"). Rejects external refs and\n"
" refs that point to the wrong component kind.\n"
).
-spec validate_ref_prefix(binary(), binary(), binary()) -> {ok, binary()} |
{error, parse_error()}.
validate_ref_prefix(Ref_str, Expected_prefix, Kind) ->
case gleam_stdlib:string_starts_with(Ref_str, Expected_prefix) of
true ->
Name = gleam@string:drop_start(
Ref_str,
string:length(Expected_prefix)
),
{ok, Name};
false ->
{error,
{invalid_value,
<<Kind/binary, ".$ref"/utf8>>,
<<<<<<<<<<"Reference '"/utf8, Ref_str/binary>>/binary,
"' is not a local "/utf8>>/binary,
Kind/binary>>/binary,
" reference. Expected prefix: "/utf8>>/binary,
Expected_prefix/binary>>}}
end.
-file("src/oaspec/openapi/parser.gleam", 597).
?DOC(" Resolve a $ref for a parameter by looking it up in components.\n").
-spec resolve_parameter_ref(
binary(),
gleam@option:option(oaspec@openapi@spec:components())
) -> {ok, oaspec@openapi@spec:parameter()} | {error, parse_error()}.
resolve_parameter_ref(Ref_str, Components) ->
gleam@result:'try'(
validate_ref_prefix(
Ref_str,
<<"#/components/parameters/"/utf8>>,
<<"parameter"/utf8>>
),
fun(Ref_name) -> case Components of
{some, Comps} ->
case gleam_stdlib:map_get(
erlang:element(3, Comps),
Ref_name
) of
{ok, Param} ->
{ok, Param};
{error, _} ->
{error,
{invalid_value,
<<"parameter.$ref"/utf8>>,
<<"Unresolved parameter reference: "/utf8,
Ref_str/binary>>}}
end;
none ->
{error,
{invalid_value,
<<"parameter.$ref"/utf8>>,
<<"No components to resolve reference: "/utf8,
Ref_str/binary>>}}
end end
).
-file("src/oaspec/openapi/parser.gleam", 626).
?DOC(" Resolve a $ref for a request body by looking it up in components.\n").
-spec resolve_request_body_ref(
binary(),
gleam@option:option(oaspec@openapi@spec:components())
) -> {ok, oaspec@openapi@spec:request_body()} | {error, parse_error()}.
resolve_request_body_ref(Ref_str, Components) ->
gleam@result:'try'(
validate_ref_prefix(
Ref_str,
<<"#/components/requestBodies/"/utf8>>,
<<"requestBody"/utf8>>
),
fun(Ref_name) -> case Components of
{some, Comps} ->
case gleam_stdlib:map_get(
erlang:element(4, Comps),
Ref_name
) of
{ok, Rb} ->
{ok, Rb};
{error, _} ->
{error,
{invalid_value,
<<"requestBody.$ref"/utf8>>,
<<"Unresolved requestBody reference: "/utf8,
Ref_str/binary>>}}
end;
none ->
{error,
{invalid_value,
<<"requestBody.$ref"/utf8>>,
<<"No components to resolve reference: "/utf8,
Ref_str/binary>>}}
end end
).
-file("src/oaspec/openapi/parser.gleam", 655).
?DOC(" Resolve a $ref for a response by looking it up in components.\n").
-spec resolve_response_ref(
binary(),
gleam@option:option(oaspec@openapi@spec:components())
) -> {ok, oaspec@openapi@spec:response()} | {error, parse_error()}.
resolve_response_ref(Ref_str, Components) ->
gleam@result:'try'(
validate_ref_prefix(
Ref_str,
<<"#/components/responses/"/utf8>>,
<<"response"/utf8>>
),
fun(Ref_name) -> case Components of
{some, Comps} ->
case gleam_stdlib:map_get(
erlang:element(5, Comps),
Ref_name
) of
{ok, Resp} ->
{ok, Resp};
{error, _} ->
{error,
{invalid_value,
<<"response.$ref"/utf8>>,
<<"Unresolved response reference: "/utf8,
Ref_str/binary>>}}
end;
none ->
{error,
{invalid_value,
<<"response.$ref"/utf8>>,
<<"No components to resolve reference: "/utf8,
Ref_str/binary>>}}
end end
).
-file("src/oaspec/openapi/parser.gleam", 684).
?DOC(" Parse parameter location string.\n").
-spec parse_parameter_in(binary()) -> {ok, oaspec@openapi@spec:parameter_in()} |
{error, parse_error()}.
parse_parameter_in(Value) ->
case Value of
<<"path"/utf8>> ->
{ok, in_path};
<<"query"/utf8>> ->
{ok, in_query};
<<"header"/utf8>> ->
{ok, in_header};
<<"cookie"/utf8>> ->
{ok, in_cookie};
_ ->
{error,
{invalid_value,
<<"parameter.in"/utf8>>,
<<<<"Unknown parameter location: "/utf8, Value/binary>>/binary,
". Must be one of: path, query, header, cookie"/utf8>>}}
end.
-file("src/oaspec/openapi/parser.gleam", 701).
?DOC(" Map a style string to a ParameterStyle ADT value.\n").
-spec parse_parameter_style(binary()) -> {ok,
oaspec@openapi@spec:parameter_style()} |
{error, parse_error()}.
parse_parameter_style(Value) ->
case Value of
<<"form"/utf8>> ->
{ok, form_style};
<<"simple"/utf8>> ->
{ok, simple_style};
<<"deepObject"/utf8>> ->
{ok, deep_object_style};
<<"matrix"/utf8>> ->
{ok, matrix_style};
<<"label"/utf8>> ->
{ok, label_style};
<<"spaceDelimited"/utf8>> ->
{ok, space_delimited_style};
<<"pipeDelimited"/utf8>> ->
{ok, pipe_delimited_style};
_ ->
{error,
{invalid_value,
<<"parameter.style"/utf8>>,
<<<<"Unknown parameter style: '"/utf8, Value/binary>>/binary,
"'. Must be one of: form, simple, deepObject, matrix, label, spaceDelimited, pipeDelimited"/utf8>>}}
end.
-file("src/oaspec/openapi/parser.gleam", 723).
?DOC(" Map an apiKey \"in\" string to a SecuritySchemeIn ADT value.\n").
-spec parse_security_scheme_in(binary()) -> {ok,
oaspec@openapi@spec:security_scheme_in()} |
{error, parse_error()}.
parse_security_scheme_in(Value) ->
case Value of
<<"header"/utf8>> ->
{ok, scheme_in_header};
<<"query"/utf8>> ->
{ok, scheme_in_query};
<<"cookie"/utf8>> ->
{ok, scheme_in_cookie};
_ ->
{error,
{invalid_value,
<<"securityScheme.in"/utf8>>,
<<<<"Unknown apiKey location: "/utf8, Value/binary>>/binary,
". Must be one of: header, query, cookie"/utf8>>}}
end.
-file("src/oaspec/openapi/parser.gleam", 1192).
?DOC(
" Check for unsupported JSON Schema 2020-12 keywords and return an error\n"
" if any are found.\n"
).
-spec check_unsupported_schema_keywords(yay:node_(), binary()) -> {ok, nil} |
{error, parse_error()}.
check_unsupported_schema_keywords(Node, Path) ->
Unsupported_keywords = [<<"const"/utf8>>,
<<"$defs"/utf8>>,
<<"prefixItems"/utf8>>,
<<"if"/utf8>>,
<<"then"/utf8>>,
<<"else"/utf8>>,
<<"dependentSchemas"/utf8>>,
<<"unevaluatedProperties"/utf8>>,
<<"unevaluatedItems"/utf8>>,
<<"contentEncoding"/utf8>>,
<<"contentMediaType"/utf8>>,
<<"contentSchema"/utf8>>,
<<"not"/utf8>>],
Found = gleam@list:filter(
Unsupported_keywords,
fun(Keyword) -> case yay:select_sugar(Node, Keyword) of
{ok, _} ->
true;
{error, _} ->
false
end end
),
case Found of
[] ->
{ok, nil};
Keywords ->
{error,
{invalid_value,
Path,
<<<<"Unsupported JSON Schema keyword '"/utf8,
(gleam@string:join(Keywords, <<"', '"/utf8>>))/binary>>/binary,
"' found. This keyword is not supported for code generation. Remove it or model the constraint differently."/utf8>>}}
end.
-file("src/oaspec/openapi/parser.gleam", 1450).
?DOC(" Parse discriminator from a node.\n").
-spec parse_discriminator(yay:node_()) -> {ok,
oaspec@openapi@schema:discriminator()} |
{error, parse_error()}.
parse_discriminator(Node) ->
gleam@result:'try'(
begin
_pipe = yay:select_sugar(Node, <<"discriminator"/utf8>>),
gleam@result:map_error(
_pipe,
fun(_) ->
{missing_field, <<"schema"/utf8>>, <<"discriminator"/utf8>>}
end
)
end,
fun(Disc_node) ->
gleam@result:'try'(
begin
_pipe@1 = yay:extract_string(
Disc_node,
<<"propertyName"/utf8>>
),
gleam@result:map_error(
_pipe@1,
fun(_) ->
{missing_field,
<<"discriminator"/utf8>>,
<<"propertyName"/utf8>>}
end
)
end,
fun(Property_name) ->
Mapping = case yay:extract_string_map(
Disc_node,
<<"mapping"/utf8>>
) of
{ok, M} ->
M;
_ ->
maps:new()
end,
{ok, {discriminator, Property_name, Mapping}}
end
)
end
).
-file("src/oaspec/openapi/parser.gleam", 1474).
?DOC(" Convert a parse error to a human-readable string.\n").
-spec parse_error_to_string(parse_error()) -> binary().
parse_error_to_string(Error) ->
case Error of
{file_error, Detail} ->
Detail;
{yaml_error, Detail@1} ->
Detail@1;
{missing_field, Path, Field} ->
Location = case Path of
<<""/utf8>> ->
<<"root"/utf8>>;
P ->
P
end,
<<<<<<<<"Missing required field '"/utf8, Field/binary>>/binary,
"' at "/utf8>>/binary,
Location/binary>>/binary,
". Check your OpenAPI spec structure."/utf8>>;
{invalid_value, Path@1, Detail@2} ->
Location@1 = case Path@1 of
<<""/utf8>> ->
<<"root"/utf8>>;
P@1 ->
P@1
end,
<<<<<<"Invalid value at "/utf8, Location@1/binary>>/binary,
": "/utf8>>/binary,
Detail@2/binary>>
end.
-file("src/oaspec/openapi/parser.gleam", 1554).
?DOC(" Resolve a $ref for a path item by looking it up in components.pathItems.\n").
-spec resolve_path_item_ref(
binary(),
gleam@option:option(oaspec@openapi@spec:components())
) -> {ok, oaspec@openapi@spec:path_item()} | {error, parse_error()}.
resolve_path_item_ref(Ref_str, Components) ->
gleam@result:'try'(
validate_ref_prefix(
Ref_str,
<<"#/components/pathItems/"/utf8>>,
<<"pathItem"/utf8>>
),
fun(Ref_name) -> case Components of
{some, Comps} ->
case gleam_stdlib:map_get(
erlang:element(7, Comps),
Ref_name
) of
{ok, Path_item} ->
{ok, Path_item};
{error, _} ->
{error,
{invalid_value,
<<"pathItem.$ref"/utf8>>,
<<"Unresolved pathItem reference: "/utf8,
Ref_str/binary>>}}
end;
none ->
{error,
{invalid_value,
<<"pathItem.$ref"/utf8>>,
<<"No components to resolve reference: "/utf8,
Ref_str/binary>>}}
end end
).
-file("src/oaspec/openapi/parser.gleam", 1661).
?DOC(" Parse OAuth2 flows from a security scheme node.\n").
-spec parse_oauth2_flows(yay:node_()) -> gleam@dict:dict(binary(), oaspec@openapi@spec:o_auth2_flow()).
parse_oauth2_flows(Node) ->
case yay:select_sugar(Node, <<"flows"/utf8>>) of
{ok, {node_map, Flow_entries}} ->
gleam@list:fold(
Flow_entries,
maps:new(),
fun(Acc, Entry) ->
{Key_node, Flow_node} = Entry,
case Key_node of
{node_str, Flow_name} ->
Authorization_url = begin
_pipe = yay:extract_optional_string(
Flow_node,
<<"authorizationUrl"/utf8>>
),
gleam@result:unwrap(_pipe, none)
end,
Token_url = begin
_pipe@1 = yay:extract_optional_string(
Flow_node,
<<"tokenUrl"/utf8>>
),
gleam@result:unwrap(_pipe@1, none)
end,
Refresh_url = begin
_pipe@2 = yay:extract_optional_string(
Flow_node,
<<"refreshUrl"/utf8>>
),
gleam@result:unwrap(_pipe@2, none)
end,
Scopes = case yay:select_sugar(
Flow_node,
<<"scopes"/utf8>>
) of
{ok, {node_map, Scope_entries}} ->
gleam@list:fold(
Scope_entries,
maps:new(),
fun(Sacc, Sentry) ->
{Sk, Sv} = Sentry,
case {Sk, Sv} of
{{node_str, Scope_name},
{node_str, Scope_desc}} ->
gleam@dict:insert(
Sacc,
Scope_name,
Scope_desc
);
{_, _} ->
Sacc
end
end
);
_ ->
maps:new()
end,
gleam@dict:insert(
Acc,
Flow_name,
{o_auth2_flow,
Authorization_url,
Token_url,
Refresh_url,
Scopes}
);
_ ->
Acc
end
end
);
_ ->
maps:new()
end.
-file("src/oaspec/openapi/parser.gleam", 1583).
?DOC(" Parse a single security scheme.\n").
-spec parse_security_scheme(yay:node_()) -> {ok,
oaspec@openapi@spec:security_scheme()} |
{error, parse_error()}.
parse_security_scheme(Node) ->
gleam@result:'try'(
begin
_pipe = yay:extract_string(Node, <<"type"/utf8>>),
gleam@result:map_error(
_pipe,
fun(_) ->
{missing_field, <<"securityScheme"/utf8>>, <<"type"/utf8>>}
end
)
end,
fun(Type_str) -> case Type_str of
<<"apiKey"/utf8>> ->
gleam@result:'try'(
begin
_pipe@1 = yay:extract_string(Node, <<"name"/utf8>>),
gleam@result:map_error(
_pipe@1,
fun(_) ->
{missing_field,
<<"securityScheme.apiKey"/utf8>>,
<<"name"/utf8>>}
end
)
end,
fun(Name) ->
gleam@result:'try'(
begin
_pipe@2 = yay:extract_string(
Node,
<<"in"/utf8>>
),
gleam@result:map_error(
_pipe@2,
fun(_) ->
{missing_field,
<<"securityScheme.apiKey"/utf8>>,
<<"in"/utf8>>}
end
)
end,
fun(In_str) ->
case parse_security_scheme_in(In_str) of
{ok, In_} ->
{ok, {api_key_scheme, Name, In_}};
{error, _} ->
{error,
{invalid_value,
<<"securityScheme.apiKey.in"/utf8>>,
<<<<"Only 'header', 'query' and 'cookie' are supported for apiKey. Got: '"/utf8,
In_str/binary>>/binary,
"'"/utf8>>}}
end
end
)
end
);
<<"http"/utf8>> ->
gleam@result:'try'(
begin
_pipe@3 = yay:extract_string(
Node,
<<"scheme"/utf8>>
),
gleam@result:map_error(
_pipe@3,
fun(_) ->
{missing_field,
<<"securityScheme.http"/utf8>>,
<<"scheme"/utf8>>}
end
)
end,
fun(Scheme) ->
Bearer_format = begin
_pipe@4 = yay:extract_optional_string(
Node,
<<"bearerFormat"/utf8>>
),
gleam@result:unwrap(_pipe@4, none)
end,
{ok, {http_scheme, Scheme, Bearer_format}}
end
);
<<"oauth2"/utf8>> ->
Description = begin
_pipe@5 = yay:extract_optional_string(
Node,
<<"description"/utf8>>
),
gleam@result:unwrap(_pipe@5, none)
end,
Flows = parse_oauth2_flows(Node),
{ok, {o_auth2_scheme, Description, Flows}};
<<"openIdConnect"/utf8>> ->
Description@1 = begin
_pipe@6 = yay:extract_optional_string(
Node,
<<"description"/utf8>>
),
gleam@result:unwrap(_pipe@6, none)
end,
gleam@result:'try'(
begin
_pipe@7 = yay:extract_string(
Node,
<<"openIdConnectUrl"/utf8>>
),
gleam@result:map_error(
_pipe@7,
fun(_) ->
{missing_field,
<<"securityScheme.openIdConnect"/utf8>>,
<<"openIdConnectUrl"/utf8>>}
end
)
end,
fun(Open_id_connect_url) ->
{ok,
{open_id_connect_scheme,
Open_id_connect_url,
Description@1}}
end
);
_ ->
{error,
{invalid_value,
<<"securityScheme.type"/utf8>>,
<<"Unsupported security scheme type: "/utf8,
Type_str/binary>>}}
end end
).
-file("src/oaspec/openapi/parser.gleam", 1502).
?DOC(
" Parse security schemes from components.\n"
" Returns Ok(empty dict) if the section is absent, Error if present but\n"
" malformed.\n"
).
-spec parse_security_schemes_map(yay:node_()) -> {ok,
gleam@dict:dict(binary(), oaspec@openapi@spec:security_scheme())} |
{error, parse_error()}.
parse_security_schemes_map(Components_node) ->
case yay:select_sugar(Components_node, <<"securitySchemes"/utf8>>) of
{ok, {node_map, Entries}} ->
gleam@list:try_fold(
Entries,
maps:new(),
fun(Acc, Entry) ->
{Key_node, Value_node} = Entry,
case Key_node of
{node_str, Name} ->
case yay:extract_optional_string(
Value_node,
<<"$ref"/utf8>>
) of
{ok, {some, _}} ->
{ok, Acc};
_ ->
gleam@result:'try'(
parse_security_scheme(Value_node),
fun(Scheme) ->
{ok,
gleam@dict:insert(
Acc,
Name,
Scheme
)}
end
)
end;
_ ->
{ok, Acc}
end
end
);
_ ->
{ok, maps:new()}
end.
-file("src/oaspec/openapi/parser.gleam", 1747).
?DOC(
" Parse a single security requirement object.\n"
" Returns one SecurityRequirement whose schemes list contains all AND-ed\n"
" scheme refs. The outer list (caller) represents OR alternatives.\n"
).
-spec parse_security_requirement_object(yay:node_(), binary()) -> {ok,
oaspec@openapi@spec:security_requirement()} |
{error, parse_error()}.
parse_security_requirement_object(Node, Context) ->
case Node of
{node_map, Entries} ->
gleam@result:'try'(
gleam@list:try_map(
Entries,
fun(Entry) ->
{Key_node, Scopes_node} = Entry,
case Key_node of
{node_str, Scheme_name} ->
gleam@result:'try'(case Scopes_node of
{node_seq, Scope_items} ->
gleam@list:try_map(
Scope_items,
fun(S) -> case S of
{node_str, V} ->
{ok, V};
_ ->
{error,
{invalid_value,
<<<<Context/binary,
".security."/utf8>>/binary,
Scheme_name/binary>>,
<<"Scope must be a string"/utf8>>}}
end end
);
node_nil ->
{ok, []};
_ ->
{error,
{invalid_value,
<<<<Context/binary,
".security."/utf8>>/binary,
Scheme_name/binary>>,
<<"Scopes must be an array of strings"/utf8>>}}
end, fun(Scopes) ->
{ok,
{security_scheme_ref,
Scheme_name,
Scopes}}
end);
_ ->
{error,
{invalid_value,
<<Context/binary, ".security"/utf8>>,
<<"Security requirement key must be a string"/utf8>>}}
end
end
),
fun(Scheme_refs) ->
{ok, {security_requirement, Scheme_refs}}
end
);
_ ->
{error,
{invalid_value,
<<Context/binary, ".security"/utf8>>,
<<"Security requirement must be an object"/utf8>>}}
end.
-file("src/oaspec/openapi/parser.gleam", 1711).
?DOC(
" Parse top-level security requirements.\n"
" Returns Ok([]) if absent, Error if present but malformed.\n"
).
-spec parse_security_requirements(yay:node_(), binary()) -> {ok,
list(oaspec@openapi@spec:security_requirement())} |
{error, parse_error()}.
parse_security_requirements(Node, Context) ->
case yay:select_sugar(Node, <<"security"/utf8>>) of
{ok, {node_seq, Items}} ->
gleam@list:try_map(
Items,
fun(Item) ->
parse_security_requirement_object(Item, Context)
end
);
_ ->
{ok, []}
end.
-file("src/oaspec/openapi/parser.gleam", 1727).
?DOC(
" Parse operation-level security requirements.\n"
" Returns Ok(None) if absent (inherits top-level), Ok(Some([])) if explicitly\n"
" empty (opts out), Ok(Some([...])) if specified.\n"
).
-spec parse_optional_security_requirements(yay:node_(), binary()) -> {ok,
gleam@option:option(list(oaspec@openapi@spec:security_requirement()))} |
{error, parse_error()}.
parse_optional_security_requirements(Node, Context) ->
case yay:select_sugar(Node, <<"security"/utf8>>) of
{ok, {node_seq, Items}} ->
gleam@result:'try'(
gleam@list:try_map(
Items,
fun(Item) ->
parse_security_requirement_object(Item, Context)
end
),
fun(Reqs) -> {ok, {some, Reqs}} end
);
_ ->
{ok, none}
end.
-file("src/oaspec/openapi/parser.gleam", 1866).
?DOC(" Parse optional contact from an info node.\n").
-spec parse_optional_contact(yay:node_()) -> gleam@option:option(oaspec@openapi@spec:contact()).
parse_optional_contact(Info_node) ->
case yay:select_sugar(Info_node, <<"contact"/utf8>>) of
{ok, Contact_node} ->
Name = begin
_pipe = yay:extract_optional_string(
Contact_node,
<<"name"/utf8>>
),
gleam@result:unwrap(_pipe, none)
end,
Url = begin
_pipe@1 = yay:extract_optional_string(
Contact_node,
<<"url"/utf8>>
),
gleam@result:unwrap(_pipe@1, none)
end,
Email = begin
_pipe@2 = yay:extract_optional_string(
Contact_node,
<<"email"/utf8>>
),
gleam@result:unwrap(_pipe@2, none)
end,
{some, {contact, Name, Url, Email}};
_ ->
none
end.
-file("src/oaspec/openapi/parser.gleam", 1885).
?DOC(" Parse optional license from an info node.\n").
-spec parse_optional_license(yay:node_()) -> gleam@option:option(oaspec@openapi@spec:license()).
parse_optional_license(Info_node) ->
case yay:select_sugar(Info_node, <<"license"/utf8>>) of
{ok, License_node} ->
case yay:extract_string(License_node, <<"name"/utf8>>) of
{ok, Name} ->
Url = begin
_pipe = yay:extract_optional_string(
License_node,
<<"url"/utf8>>
),
gleam@result:unwrap(_pipe, none)
end,
{some, {license, Name, Url}};
_ ->
none
end;
_ ->
none
end.
-file("src/oaspec/openapi/parser.gleam", 126).
?DOC(" Parse the info object.\n").
-spec parse_info(yay:node_()) -> {ok, oaspec@openapi@spec:info()} |
{error, parse_error()}.
parse_info(Root) ->
gleam@result:'try'(
begin
_pipe = yay:select_sugar(Root, <<"info"/utf8>>),
gleam@result:map_error(
_pipe,
fun(_) -> {missing_field, <<""/utf8>>, <<"info"/utf8>>} end
)
end,
fun(Info_node) ->
gleam@result:'try'(
begin
_pipe@1 = yay:extract_string(Info_node, <<"title"/utf8>>),
gleam@result:map_error(
_pipe@1,
fun(_) ->
{missing_field, <<"info"/utf8>>, <<"title"/utf8>>}
end
)
end,
fun(Title) ->
gleam@result:'try'(
begin
_pipe@2 = yay:extract_string(
Info_node,
<<"version"/utf8>>
),
gleam@result:map_error(
_pipe@2,
fun(_) ->
{missing_field,
<<"info"/utf8>>,
<<"version"/utf8>>}
end
)
end,
fun(Version) ->
Description = begin
_pipe@3 = yay:extract_optional_string(
Info_node,
<<"description"/utf8>>
),
gleam@result:unwrap(_pipe@3, none)
end,
Summary = begin
_pipe@4 = yay:extract_optional_string(
Info_node,
<<"summary"/utf8>>
),
gleam@result:unwrap(_pipe@4, none)
end,
Terms_of_service = begin
_pipe@5 = yay:extract_optional_string(
Info_node,
<<"termsOfService"/utf8>>
),
gleam@result:unwrap(_pipe@5, none)
end,
Contact = parse_optional_contact(Info_node),
License = parse_optional_license(Info_node),
{ok,
{info,
Title,
Description,
Version,
Summary,
Terms_of_service,
Contact,
License}}
end
)
end
)
end
).
-file("src/oaspec/openapi/parser.gleam", 1903).
?DOC(" Parse server variables from a server node.\n").
-spec parse_server_variables(yay:node_()) -> gleam@dict:dict(binary(), oaspec@openapi@spec:server_variable()).
parse_server_variables(Node) ->
case yay:select_sugar(Node, <<"variables"/utf8>>) of
{ok, {node_map, Entries}} ->
gleam@list:fold(
Entries,
maps:new(),
fun(Acc, Entry) ->
{Key_node, Value_node} = Entry,
case Key_node of
{node_str, Var_name} ->
Default = begin
_pipe = yay:extract_optional_string(
Value_node,
<<"default"/utf8>>
),
_pipe@1 = gleam@result:unwrap(_pipe, none),
gleam@option:unwrap(_pipe@1, <<""/utf8>>)
end,
Enum_values = case yay:extract_string_list(
Value_node,
<<"enum"/utf8>>
) of
{ok, Values} ->
Values;
_ ->
[]
end,
Description = begin
_pipe@2 = yay:extract_optional_string(
Value_node,
<<"description"/utf8>>
),
gleam@result:unwrap(_pipe@2, none)
end,
gleam@dict:insert(
Acc,
Var_name,
{server_variable,
Default,
Enum_values,
Description}
);
_ ->
Acc
end
end
);
_ ->
maps:new()
end.
-file("src/oaspec/openapi/parser.gleam", 177).
?DOC(" Parse a single server object.\n").
-spec parse_server(yay:node_()) -> {ok, oaspec@openapi@spec:server()} |
{error, parse_error()}.
parse_server(Node) ->
gleam@result:'try'(
begin
_pipe = yay:extract_string(Node, <<"url"/utf8>>),
gleam@result:map_error(
_pipe,
fun(_) ->
{missing_field, <<"servers"/utf8>>, <<"url"/utf8>>}
end
)
end,
fun(Url) ->
Description = begin
_pipe@1 = yay:extract_optional_string(
Node,
<<"description"/utf8>>
),
gleam@result:unwrap(_pipe@1, none)
end,
Variables = parse_server_variables(Node),
{ok, {server, Url, Description, Variables}}
end
).
-file("src/oaspec/openapi/parser.gleam", 169).
?DOC(" Parse servers array.\n").
-spec parse_servers(yay:node_()) -> {ok, list(oaspec@openapi@spec:server())} |
{error, parse_error()}.
parse_servers(Root) ->
case yay:select_sugar(Root, <<"servers"/utf8>>) of
{ok, {node_seq, Items}} ->
gleam@list:try_map(Items, fun parse_server/1);
_ ->
{ok, []}
end.
-file("src/oaspec/openapi/parser.gleam", 1935).
?DOC(" Parse optional external docs from a node.\n").
-spec parse_optional_external_docs(yay:node_()) -> gleam@option:option(oaspec@openapi@spec:external_doc()).
parse_optional_external_docs(Node) ->
case yay:select_sugar(Node, <<"externalDocs"/utf8>>) of
{ok, Doc_node} ->
case yay:extract_string(Doc_node, <<"url"/utf8>>) of
{ok, Url} ->
Description = begin
_pipe = yay:extract_optional_string(
Doc_node,
<<"description"/utf8>>
),
gleam@result:unwrap(_pipe, none)
end,
{some, {external_doc, Url, Description}};
_ ->
none
end;
_ ->
none
end.
-file("src/oaspec/openapi/parser.gleam", 1953).
?DOC(" Parse tags array from root.\n").
-spec parse_tags(yay:node_()) -> list(oaspec@openapi@spec:tag()).
parse_tags(Node) ->
case yay:select_sugar(Node, <<"tags"/utf8>>) of
{ok, {node_seq, Items}} ->
gleam@list:filter_map(
Items,
fun(Tag_node) ->
case yay:extract_string(Tag_node, <<"name"/utf8>>) of
{ok, Name} ->
Description = begin
_pipe = yay:extract_optional_string(
Tag_node,
<<"description"/utf8>>
),
gleam@result:unwrap(_pipe, none)
end,
External_docs = parse_optional_external_docs(
Tag_node
),
{ok, {tag, Name, Description, External_docs}};
_ ->
{error, nil}
end
end
);
_ ->
[]
end.
-file("src/oaspec/openapi/parser.gleam", 1999).
?DOC(" Parse a string->string map from a node at a given key.\n").
-spec parse_string_map(yay:node_(), binary()) -> gleam@dict:dict(binary(), binary()).
parse_string_map(Node, Key) ->
case yay:extract_string_map(Node, Key) of
{ok, M} ->
M;
_ ->
maps:new()
end.
-file("src/oaspec/openapi/parser.gleam", 2048).
?DOC(" Parse encoding map from a media type node.\n").
-spec parse_encoding_map(yay:node_()) -> gleam@dict:dict(binary(), oaspec@openapi@spec:encoding()).
parse_encoding_map(Node) ->
case yay:select_sugar(Node, <<"encoding"/utf8>>) of
{ok, {node_map, Entries}} ->
gleam@list:fold(
Entries,
maps:new(),
fun(Acc, Entry) ->
{Key_node, Value_node} = Entry,
case Key_node of
{node_str, Prop_name} ->
Content_type = begin
_pipe = yay:extract_optional_string(
Value_node,
<<"contentType"/utf8>>
),
gleam@result:unwrap(_pipe, none)
end,
Style = begin
_pipe@1 = yay:extract_optional_string(
Value_node,
<<"style"/utf8>>
),
_pipe@2 = gleam@result:unwrap(_pipe@1, none),
_pipe@3 = gleam@option:map(
_pipe@2,
fun(S) -> case parse_parameter_style(S) of
{ok, Parsed} ->
{some, Parsed};
{error, _} ->
none
end end
),
gleam@option:flatten(_pipe@3)
end,
Explode = begin
_pipe@4 = yay:extract_optional_bool(
Value_node,
<<"explode"/utf8>>
),
gleam@result:unwrap(_pipe@4, none)
end,
gleam@dict:insert(
Acc,
Prop_name,
{encoding, Content_type, Style, Explode}
);
_ ->
Acc
end
end
);
_ ->
maps:new()
end.
-file("src/oaspec/openapi/parser.gleam", 2128).
?DOC(" Parse links map from a node.\n").
-spec parse_links_map(yay:node_()) -> gleam@dict:dict(binary(), oaspec@openapi@spec:link()).
parse_links_map(Node) ->
case yay:select_sugar(Node, <<"links"/utf8>>) of
{ok, {node_map, Entries}} ->
gleam@list:fold(
Entries,
maps:new(),
fun(Acc, Entry) ->
{Key_node, Value_node} = Entry,
case Key_node of
{node_str, Link_name} ->
Operation_id = begin
_pipe = yay:extract_optional_string(
Value_node,
<<"operationId"/utf8>>
),
gleam@result:unwrap(_pipe, none)
end,
Description = begin
_pipe@1 = yay:extract_optional_string(
Value_node,
<<"description"/utf8>>
),
gleam@result:unwrap(_pipe@1, none)
end,
gleam@dict:insert(
Acc,
Link_name,
{link, Operation_id, Description}
);
_ ->
Acc
end
end
);
_ ->
maps:new()
end.
-file("src/oaspec/openapi/parser.gleam", 2151).
?DOC(" Convert a YAML error to a string.\n").
-spec yaml_error_to_string(yay:yaml_error()) -> binary().
yaml_error_to_string(Error) ->
case Error of
unexpected_parsing_error ->
<<"Unexpected parsing error"/utf8>>;
{parsing_error, Msg, _} ->
Msg
end.
-file("src/oaspec/openapi/parser.gleam", 1828).
?DOC(
" Parse a single callback object (maps URL expressions -> PathItems).\n"
" Propagates parse errors from individual URL expression path items.\n"
).
-spec parse_callback_object(
yay:node_(),
binary(),
gleam@option:option(oaspec@openapi@spec:components())
) -> {ok, oaspec@openapi@spec:callback()} | {error, parse_error()}.
parse_callback_object(Node, Context, Components) ->
case Node of
{node_map, Entries} ->
gleam@result:'try'(
gleam@list:try_fold(
Entries,
[],
fun(Acc, Entry) ->
{Key_node, Path_item_node} = Entry,
case Key_node of
{node_str, Url_expression} ->
gleam@result:'try'(
parse_path_item(
Path_item_node,
<<<<Context/binary, ".callbacks."/utf8>>/binary,
Url_expression/binary>>,
Components
),
fun(Path_item) ->
{ok,
[{Url_expression, Path_item} | Acc]}
end
);
_ ->
{ok, Acc}
end
end
),
fun(Parsed_entries) -> case Parsed_entries of
[] ->
{error,
{missing_field,
<<Context/binary, ".callbacks"/utf8>>,
<<"url expression"/utf8>>}};
_ ->
{ok, {callback, maps:from_list(Parsed_entries)}}
end end
);
_ ->
{error,
{missing_field,
<<Context/binary, ".callbacks"/utf8>>,
<<"url expression"/utf8>>}}
end.
-file("src/oaspec/openapi/parser.gleam", 228).
?DOC(" Parse a single path item.\n").
-spec parse_path_item(
yay:node_(),
binary(),
gleam@option:option(oaspec@openapi@spec:components())
) -> {ok, oaspec@openapi@spec:path_item()} | {error, parse_error()}.
parse_path_item(Node, Path, Components) ->
Summary = begin
_pipe = yay:extract_optional_string(Node, <<"summary"/utf8>>),
gleam@result:unwrap(_pipe, none)
end,
Description = begin
_pipe@1 = yay:extract_optional_string(Node, <<"description"/utf8>>),
gleam@result:unwrap(_pipe@1, none)
end,
gleam@result:'try'(
parse_optional_operation(Node, <<"get"/utf8>>, Path, get, Components),
fun(Get) ->
gleam@result:'try'(
parse_optional_operation(
Node,
<<"post"/utf8>>,
Path,
post,
Components
),
fun(Post) ->
gleam@result:'try'(
parse_optional_operation(
Node,
<<"put"/utf8>>,
Path,
put,
Components
),
fun(Put) ->
gleam@result:'try'(
parse_optional_operation(
Node,
<<"delete"/utf8>>,
Path,
delete,
Components
),
fun(Delete) ->
gleam@result:'try'(
parse_optional_operation(
Node,
<<"patch"/utf8>>,
Path,
patch,
Components
),
fun(Patch) ->
gleam@result:'try'(
parse_optional_operation(
Node,
<<"head"/utf8>>,
Path,
head,
Components
),
fun(Head) ->
gleam@result:'try'(
parse_optional_operation(
Node,
<<"options"/utf8>>,
Path,
options,
Components
),
fun(Options) ->
gleam@result:'try'(
parse_optional_operation(
Node,
<<"trace"/utf8>>,
Path,
trace,
Components
),
fun(Trace) ->
gleam@result:'try'(
parse_parameters_list(
Node,
Components
),
fun(
Parameters
) ->
gleam@result:'try'(
parse_servers(
Node
),
fun(
Servers
) ->
{ok,
{path_item,
Summary,
Description,
Get,
Post,
Put,
Delete,
Patch,
Head,
Options,
Trace,
Parameters,
Servers}}
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
).
-file("src/oaspec/openapi/parser.gleam", 320).
?DOC(
" Parse an optional operation: Ok(None) if key absent, Ok(Some(..)) if valid,\n"
" Error if present but malformed.\n"
).
-spec parse_optional_operation(
yay:node_(),
binary(),
binary(),
oaspec@openapi@spec:http_method(),
gleam@option:option(oaspec@openapi@spec:components())
) -> {ok, gleam@option:option(oaspec@openapi@spec:operation())} |
{error, parse_error()}.
parse_optional_operation(Node, Method_key, Path, Method, Components) ->
case yay:select_sugar(Node, Method_key) of
{ok, _} ->
gleam@result:'try'(
parse_operation_at(Node, Method_key, Path, Method, Components),
fun(Op) -> {ok, {some, Op}} end
);
{error, _} ->
{ok, none}
end.
-file("src/oaspec/openapi/parser.gleam", 343).
?DOC(" Parse an operation at a specific HTTP method key.\n").
-spec parse_operation_at(
yay:node_(),
binary(),
binary(),
oaspec@openapi@spec:http_method(),
gleam@option:option(oaspec@openapi@spec:components())
) -> {ok, oaspec@openapi@spec:operation()} | {error, parse_error()}.
parse_operation_at(Node, Method_key, Path, _, Components) ->
gleam@result:'try'(
begin
_pipe = yay:select_sugar(Node, Method_key),
gleam@result:map_error(
_pipe,
fun(_) -> {missing_field, Path, Method_key} end
)
end,
fun(Op_node) ->
parse_operation(
Op_node,
<<<<Path/binary, "."/utf8>>/binary, Method_key/binary>>,
Components
)
end
).
-file("src/oaspec/openapi/parser.gleam", 359).
?DOC(" Parse a single operation.\n").
-spec parse_operation(
yay:node_(),
binary(),
gleam@option:option(oaspec@openapi@spec:components())
) -> {ok, oaspec@openapi@spec:operation()} | {error, parse_error()}.
parse_operation(Node, Context, Components) ->
Operation_id = begin
_pipe = yay:extract_optional_string(Node, <<"operationId"/utf8>>),
gleam@result:unwrap(_pipe, none)
end,
Summary = begin
_pipe@1 = yay:extract_optional_string(Node, <<"summary"/utf8>>),
gleam@result:unwrap(_pipe@1, none)
end,
Description = begin
_pipe@2 = yay:extract_optional_string(Node, <<"description"/utf8>>),
gleam@result:unwrap(_pipe@2, none)
end,
Tags = case yay:extract_string_list(Node, <<"tags"/utf8>>) of
{ok, T} ->
T;
_ ->
[]
end,
Deprecated = begin
_pipe@3 = yay:extract_optional_bool(Node, <<"deprecated"/utf8>>),
_pipe@4 = gleam@result:unwrap(_pipe@3, none),
gleam@option:unwrap(_pipe@4, false)
end,
gleam@result:'try'(
parse_parameters_list(Node, Components),
fun(Parameters) ->
gleam@result:'try'(
parse_optional_request_body(Node, Context, Components),
fun(Request_body) ->
gleam@result:'try'(
parse_responses_required(Node, Context, Components),
fun(Responses) ->
gleam@result:'try'(
parse_optional_security_requirements(
Node,
Context
),
fun(Security) ->
gleam@result:'try'(
parse_callbacks(
Node,
Context,
Components
),
fun(Callbacks) ->
gleam@result:'try'(
parse_servers(Node),
fun(Op_servers) ->
External_docs = parse_optional_external_docs(
Node
),
{ok,
{operation,
Operation_id,
Summary,
Description,
Tags,
Parameters,
Request_body,
Responses,
Deprecated,
Security,
Callbacks,
Op_servers,
External_docs}}
end
)
end
)
end
)
end
)
end
)
end
).
-file("src/oaspec/openapi/parser.gleam", 1800).
?DOC(
" Parse callbacks from an operation node.\n"
" Returns an empty dict if no callbacks are present.\n"
" Propagates parse errors instead of silently dropping invalid callbacks.\n"
).
-spec parse_callbacks(
yay:node_(),
binary(),
gleam@option:option(oaspec@openapi@spec:components())
) -> {ok, gleam@dict:dict(binary(), oaspec@openapi@spec:callback())} |
{error, parse_error()}.
parse_callbacks(Node, Context, Components) ->
case yay:select_sugar(Node, <<"callbacks"/utf8>>) of
{ok, {node_map, Entries}} ->
gleam@list:try_fold(
Entries,
maps:new(),
fun(Acc, Entry) ->
{Key_node, Value_node} = Entry,
case Key_node of
{node_str, Callback_name} ->
gleam@result:'try'(
parse_callback_object(
Value_node,
Context,
Components
),
fun(Callback) ->
{ok,
gleam@dict:insert(
Acc,
Callback_name,
Callback
)}
end
);
_ ->
{ok, Acc}
end
end
);
_ ->
{ok, maps:new()}
end.
-file("src/oaspec/openapi/parser.gleam", 193).
?DOC(" Parse the paths object.\n").
-spec parse_paths(
yay:node_(),
gleam@option:option(oaspec@openapi@spec:components())
) -> {ok, gleam@dict:dict(binary(), oaspec@openapi@spec:path_item())} |
{error, parse_error()}.
parse_paths(Root, Components) ->
case yay:select_sugar(Root, <<"paths"/utf8>>) of
{ok, {node_map, Entries}} ->
gleam@list:try_fold(
Entries,
maps:new(),
fun(Acc, Entry) ->
{Key_node, Value_node} = Entry,
case Key_node of
{node_str, Path} ->
case gleam_stdlib:string_starts_with(
Path,
<<"x-"/utf8>>
) of
true ->
{ok, Acc};
false ->
gleam@result:'try'(
case begin
_pipe = yay:extract_optional_string(
Value_node,
<<"$ref"/utf8>>
),
gleam@result:unwrap(_pipe, none)
end of
{some, Ref_str} ->
resolve_path_item_ref(
Ref_str,
Components
);
none ->
parse_path_item(
Value_node,
Path,
Components
)
end,
fun(Path_item) ->
{ok,
gleam@dict:insert(
Acc,
Path,
Path_item
)}
end
)
end;
_ ->
{ok, Acc}
end
end
);
_ ->
{ok, maps:new()}
end.
-file("src/oaspec/openapi/parser.gleam", 1529).
?DOC(" Parse the pathItems map from components.\n").
-spec parse_path_items_map(yay:node_()) -> {ok,
gleam@dict:dict(binary(), oaspec@openapi@spec:path_item())} |
{error, parse_error()}.
parse_path_items_map(Components_node) ->
case yay:select_sugar(Components_node, <<"pathItems"/utf8>>) of
{ok, {node_map, Entries}} ->
gleam@list:try_fold(
Entries,
maps:new(),
fun(Acc, Entry) ->
{Key_node, Value_node} = Entry,
case Key_node of
{node_str, Name} ->
gleam@result:'try'(
parse_path_item(
Value_node,
<<"components.pathItems."/utf8,
Name/binary>>,
none
),
fun(Path_item) ->
{ok,
gleam@dict:insert(Acc, Name, Path_item)}
end
);
_ ->
{ok, Acc}
end
end
);
_ ->
{ok, maps:new()}
end.
-file("src/oaspec/openapi/parser.gleam", 1973).
?DOC(" Parse webhooks from root.\n").
-spec parse_webhooks(
yay:node_(),
gleam@option:option(oaspec@openapi@spec:components())
) -> {ok, gleam@dict:dict(binary(), oaspec@openapi@spec:path_item())} |
{error, parse_error()}.
parse_webhooks(Node, Components) ->
case yay:select_sugar(Node, <<"webhooks"/utf8>>) of
{ok, {node_map, Entries}} ->
gleam@list:try_fold(
Entries,
maps:new(),
fun(Acc, Entry) ->
{Key_node, Value_node} = Entry,
case Key_node of
{node_str, Name} ->
gleam@result:'try'(
parse_path_item(
Value_node,
<<"webhooks."/utf8, Name/binary>>,
Components
),
fun(Path_item) ->
{ok,
gleam@dict:insert(Acc, Name, Path_item)}
end
);
_ ->
{ok, Acc}
end
end
);
_ ->
{ok, maps:new()}
end.
-file("src/oaspec/openapi/parser.gleam", 1088).
?DOC(" Parse a schema object.\n").
-spec parse_schema_object(yay:node_(), binary()) -> {ok,
oaspec@openapi@schema:schema_object()} |
{error, parse_error()}.
parse_schema_object(Node, Path) ->
Nullable = begin
_pipe = yay:extract_optional_bool(Node, <<"nullable"/utf8>>),
_pipe@1 = gleam@result:unwrap(_pipe, none),
gleam@option:unwrap(_pipe@1, false)
end,
Description = begin
_pipe@2 = yay:extract_optional_string(Node, <<"description"/utf8>>),
gleam@result:unwrap(_pipe@2, none)
end,
Deprecated = begin
_pipe@3 = yay:extract_optional_bool(Node, <<"deprecated"/utf8>>),
_pipe@4 = gleam@result:unwrap(_pipe@3, none),
gleam@option:unwrap(_pipe@4, false)
end,
Title = begin
_pipe@5 = yay:extract_optional_string(Node, <<"title"/utf8>>),
gleam@result:unwrap(_pipe@5, none)
end,
Read_only = begin
_pipe@6 = yay:extract_optional_bool(Node, <<"readOnly"/utf8>>),
_pipe@7 = gleam@result:unwrap(_pipe@6, none),
gleam@option:unwrap(_pipe@7, false)
end,
Write_only = begin
_pipe@8 = yay:extract_optional_bool(Node, <<"writeOnly"/utf8>>),
_pipe@9 = gleam@result:unwrap(_pipe@8, none),
gleam@option:unwrap(_pipe@9, false)
end,
Default = begin
_pipe@10 = yay:extract_optional_string(Node, <<"default"/utf8>>),
gleam@result:unwrap(_pipe@10, none)
end,
Example = begin
_pipe@11 = yay:extract_optional_string(Node, <<"example"/utf8>>),
gleam@result:unwrap(_pipe@11, none)
end,
Metadata = {schema_metadata,
Description,
Nullable,
Deprecated,
Title,
Read_only,
Write_only,
Default,
Example},
gleam@result:'try'(
check_unsupported_schema_keywords(Node, Path),
fun(_) -> case yay:select_sugar(Node, <<"allOf"/utf8>>) of
{ok, {node_seq, Items}} ->
gleam@result:'try'(
gleam@list:try_map(
Items,
fun(_capture) ->
parse_schema_ref(
_capture,
<<Path/binary, ".allOf"/utf8>>
)
end
),
fun(Schemas) ->
{ok, {all_of_schema, Metadata, Schemas}}
end
);
_ ->
case yay:select_sugar(Node, <<"oneOf"/utf8>>) of
{ok, {node_seq, Items@1}} ->
gleam@result:'try'(
gleam@list:try_map(
Items@1,
fun(_capture@1) ->
parse_schema_ref(
_capture@1,
<<Path/binary, ".oneOf"/utf8>>
)
end
),
fun(Schemas@1) ->
gleam@result:'try'(
case yay:select_sugar(
Node,
<<"discriminator"/utf8>>
) of
{ok, _} ->
gleam@result:'try'(
parse_discriminator(Node),
fun(D) ->
{ok, {some, D}}
end
);
{error, _} ->
{ok, none}
end,
fun(Discriminator) ->
{ok,
{one_of_schema,
Metadata,
Schemas@1,
Discriminator}}
end
)
end
);
_ ->
case yay:select_sugar(Node, <<"anyOf"/utf8>>) of
{ok, {node_seq, Items@2}} ->
gleam@result:'try'(
gleam@list:try_map(
Items@2,
fun(_capture@2) ->
parse_schema_ref(
_capture@2,
<<Path/binary,
".anyOf"/utf8>>
)
end
),
fun(Schemas@2) ->
gleam@result:'try'(
case yay:select_sugar(
Node,
<<"discriminator"/utf8>>
) of
{ok, _} ->
gleam@result:'try'(
parse_discriminator(
Node
),
fun(D@1) ->
{ok,
{some, D@1}}
end
);
{error, _} ->
{ok, none}
end,
fun(Discriminator@1) ->
{ok,
{any_of_schema,
Metadata,
Schemas@2,
Discriminator@1}}
end
)
end
);
_ ->
parse_typed_schema(Node, Metadata, Path)
end
end
end end
).
-file("src/oaspec/openapi/parser.gleam", 1221).
?DOC(" Parse a typed schema (string, integer, number, boolean, array, object).\n").
-spec parse_typed_schema(
yay:node_(),
oaspec@openapi@schema:schema_metadata(),
binary()
) -> {ok, oaspec@openapi@schema:schema_object()} | {error, parse_error()}.
parse_typed_schema(Node, Metadata, Path) ->
gleam@result:'try'(case yay:select_sugar(Node, <<"type"/utf8>>) of
{ok, {node_seq, Type_nodes}} ->
Type_strs = gleam@list:filter_map(
Type_nodes,
fun(N) -> case N of
{node_str, S} ->
{ok, S};
_ ->
{error, nil}
end end
),
Has_null = gleam@list:contains(Type_strs, <<"null"/utf8>>),
Non_null_types = gleam@list:filter(
Type_strs,
fun(S@1) -> S@1 /= <<"null"/utf8>> end
),
case Non_null_types of
[Single] ->
{ok,
{Single,
{schema_metadata,
erlang:element(2, Metadata),
erlang:element(3, Metadata) orelse Has_null,
erlang:element(4, Metadata),
erlang:element(5, Metadata),
erlang:element(6, Metadata),
erlang:element(7, Metadata),
erlang:element(8, Metadata),
erlang:element(9, Metadata)}}};
[] ->
{ok,
{<<"object"/utf8>>,
{schema_metadata,
erlang:element(2, Metadata),
erlang:element(3, Metadata) orelse Has_null,
erlang:element(4, Metadata),
erlang:element(5, Metadata),
erlang:element(6, Metadata),
erlang:element(7, Metadata),
erlang:element(8, Metadata),
erlang:element(9, Metadata)}}};
_ ->
{error,
{invalid_value,
<<Path/binary, ".type"/utf8>>,
<<<<"Multi-type unions (type: ["/utf8,
(gleam@string:join(
Non_null_types,
<<", "/utf8>>
))/binary>>/binary,
"]) are not supported; use oneOf instead"/utf8>>}}
end;
{ok, {node_str, S@2}} ->
{ok, {S@2, Metadata}};
_ ->
S@3 = begin
_pipe = yay:extract_optional_string(Node, <<"type"/utf8>>),
_pipe@1 = gleam@result:unwrap(_pipe, none),
gleam@option:unwrap(_pipe@1, <<"object"/utf8>>)
end,
{ok, {S@3, Metadata}}
end, fun(_use0) ->
{Type_str, Metadata@1} = _use0,
Format = begin
_pipe@2 = yay:extract_optional_string(Node, <<"format"/utf8>>),
gleam@result:unwrap(_pipe@2, none)
end,
case Type_str of
<<"string"/utf8>> ->
Enum_values = case yay:extract_string_list(
Node,
<<"enum"/utf8>>
) of
{ok, Values} ->
Values;
_ ->
[]
end,
Min_length = begin
_pipe@3 = yay:extract_optional_int(
Node,
<<"minLength"/utf8>>
),
gleam@result:unwrap(_pipe@3, none)
end,
Max_length = begin
_pipe@4 = yay:extract_optional_int(
Node,
<<"maxLength"/utf8>>
),
gleam@result:unwrap(_pipe@4, none)
end,
Pattern = begin
_pipe@5 = yay:extract_optional_string(
Node,
<<"pattern"/utf8>>
),
gleam@result:unwrap(_pipe@5, none)
end,
{ok,
{string_schema,
Metadata@1,
Format,
Enum_values,
Min_length,
Max_length,
Pattern}};
<<"integer"/utf8>> ->
Minimum = begin
_pipe@6 = yay:extract_optional_int(
Node,
<<"minimum"/utf8>>
),
gleam@result:unwrap(_pipe@6, none)
end,
Maximum = begin
_pipe@7 = yay:extract_optional_int(
Node,
<<"maximum"/utf8>>
),
gleam@result:unwrap(_pipe@7, none)
end,
Exclusive_minimum = begin
_pipe@8 = yay:extract_optional_int(
Node,
<<"exclusiveMinimum"/utf8>>
),
gleam@result:unwrap(_pipe@8, none)
end,
Exclusive_maximum = begin
_pipe@9 = yay:extract_optional_int(
Node,
<<"exclusiveMaximum"/utf8>>
),
gleam@result:unwrap(_pipe@9, none)
end,
Multiple_of = begin
_pipe@10 = yay:extract_optional_int(
Node,
<<"multipleOf"/utf8>>
),
gleam@result:unwrap(_pipe@10, none)
end,
{ok,
{integer_schema,
Metadata@1,
Format,
Minimum,
Maximum,
Exclusive_minimum,
Exclusive_maximum,
Multiple_of}};
<<"number"/utf8>> ->
Minimum@1 = begin
_pipe@11 = yay:extract_optional_float(
Node,
<<"minimum"/utf8>>
),
gleam@result:unwrap(_pipe@11, none)
end,
Maximum@1 = begin
_pipe@12 = yay:extract_optional_float(
Node,
<<"maximum"/utf8>>
),
gleam@result:unwrap(_pipe@12, none)
end,
Exclusive_minimum@1 = begin
_pipe@13 = yay:extract_optional_float(
Node,
<<"exclusiveMinimum"/utf8>>
),
gleam@result:unwrap(_pipe@13, none)
end,
Exclusive_maximum@1 = begin
_pipe@14 = yay:extract_optional_float(
Node,
<<"exclusiveMaximum"/utf8>>
),
gleam@result:unwrap(_pipe@14, none)
end,
Multiple_of@1 = begin
_pipe@15 = yay:extract_optional_float(
Node,
<<"multipleOf"/utf8>>
),
gleam@result:unwrap(_pipe@15, none)
end,
{ok,
{number_schema,
Metadata@1,
Format,
Minimum@1,
Maximum@1,
Exclusive_minimum@1,
Exclusive_maximum@1,
Multiple_of@1}};
<<"boolean"/utf8>> ->
{ok, {boolean_schema, Metadata@1}};
<<"array"/utf8>> ->
gleam@result:'try'(
case yay:select_sugar(Node, <<"items"/utf8>>) of
{ok, Items_node} ->
parse_schema_ref(
Items_node,
<<Path/binary, ".items"/utf8>>
);
_ ->
{error, {missing_field, Path, <<"items"/utf8>>}}
end,
fun(Items) ->
Min_items = begin
_pipe@16 = yay:extract_optional_int(
Node,
<<"minItems"/utf8>>
),
gleam@result:unwrap(_pipe@16, none)
end,
Max_items = begin
_pipe@17 = yay:extract_optional_int(
Node,
<<"maxItems"/utf8>>
),
gleam@result:unwrap(_pipe@17, none)
end,
Unique_items = begin
_pipe@18 = yay:extract_optional_bool(
Node,
<<"uniqueItems"/utf8>>
),
_pipe@19 = gleam@result:unwrap(_pipe@18, none),
gleam@option:unwrap(_pipe@19, false)
end,
{ok,
{array_schema,
Metadata@1,
Items,
Min_items,
Max_items,
Unique_items}}
end
);
<<"object"/utf8>> ->
gleam@result:'try'(
parse_properties(Node, Path),
fun(Properties) ->
Required = case yay:extract_string_list(
Node,
<<"required"/utf8>>
) of
{ok, R} ->
R;
_ ->
[]
end,
gleam@result:'try'(
case yay:select_sugar(
Node,
<<"additionalProperties"/utf8>>
) of
{ok, {node_bool, true}} ->
{ok, {none, true}};
{ok, {node_bool, false}} ->
{ok, {none, false}};
{ok, Ap_node} ->
gleam@result:'try'(
parse_schema_ref(
Ap_node,
<<Path/binary,
".additionalProperties"/utf8>>
),
fun(Sr) ->
{ok, {{some, Sr}, false}}
end
);
_ ->
{ok, {none, false}}
end,
fun(_use0@1) ->
{Additional_properties,
Additional_properties_untyped} = _use0@1,
Min_properties = begin
_pipe@20 = yay:extract_optional_int(
Node,
<<"minProperties"/utf8>>
),
gleam@result:unwrap(_pipe@20, none)
end,
Max_properties = begin
_pipe@21 = yay:extract_optional_int(
Node,
<<"maxProperties"/utf8>>
),
gleam@result:unwrap(_pipe@21, none)
end,
{ok,
{object_schema,
Metadata@1,
Properties,
Required,
Additional_properties,
Additional_properties_untyped,
Min_properties,
Max_properties}}
end
)
end
);
Unrecognized ->
{error,
{invalid_value,
<<Path/binary, ".type"/utf8>>,
<<<<"Unrecognized schema type '"/utf8,
Unrecognized/binary>>/binary,
"'. Supported types: string, integer, number, boolean, array, object."/utf8>>}}
end
end).
-file("src/oaspec/openapi/parser.gleam", 1425).
?DOC(" Parse properties map from an object schema.\n").
-spec parse_properties(yay:node_(), binary()) -> {ok,
gleam@dict:dict(binary(), oaspec@openapi@schema:schema_ref())} |
{error, parse_error()}.
parse_properties(Node, Path) ->
case yay:select_sugar(Node, <<"properties"/utf8>>) of
{ok, {node_map, Entries}} ->
gleam@list:try_fold(
Entries,
maps:new(),
fun(Acc, Entry) ->
{Key_node, Value_node} = Entry,
case Key_node of
{node_str, Prop_name} ->
gleam@result:'try'(
parse_schema_ref(
Value_node,
<<<<Path/binary, "."/utf8>>/binary,
Prop_name/binary>>
),
fun(Schema_ref) ->
{ok,
gleam@dict:insert(
Acc,
Prop_name,
Schema_ref
)}
end
);
_ ->
{ok, Acc}
end
end
);
_ ->
{ok, maps:new()}
end.
-file("src/oaspec/openapi/parser.gleam", 1074).
?DOC(" Parse a schema reference (either $ref or inline schema).\n").
-spec parse_schema_ref(yay:node_(), binary()) -> {ok,
oaspec@openapi@schema:schema_ref()} |
{error, parse_error()}.
parse_schema_ref(Node, Path) ->
case yay:extract_optional_string(Node, <<"$ref"/utf8>>) of
{ok, {some, Ref}} ->
{ok, oaspec@openapi@schema:make_reference(Ref)};
_ ->
gleam@result:'try'(
parse_schema_object(Node, Path),
fun(Schema_obj) -> {ok, {inline, Schema_obj}} end
)
end.
-file("src/oaspec/openapi/parser.gleam", 781).
?DOC(" Parse content map, requiring at least one entry for request bodies.\n").
-spec parse_required_content(yay:node_(), binary()) -> {ok,
gleam@dict:dict(binary(), oaspec@openapi@spec:media_type())} |
{error, parse_error()}.
parse_required_content(Node, Context) ->
case yay:select_sugar(Node, <<"content"/utf8>>) of
{ok, {node_map, Entries}} ->
gleam@list:try_fold(
Entries,
maps:new(),
fun(Acc, Entry) ->
{Key_node, Value_node} = Entry,
case Key_node of
{node_str, Media_type_name} ->
gleam@result:'try'(
case yay:select_sugar(
Value_node,
<<"schema"/utf8>>
) of
{ok, Schema_node} ->
gleam@result:'try'(
parse_schema_ref(
Schema_node,
<<Context/binary,
".schema"/utf8>>
),
fun(Sr) -> {ok, {some, Sr}} end
);
_ ->
{ok, none}
end,
fun(Mt_schema) ->
Mt_example = begin
_pipe = yay:extract_optional_string(
Value_node,
<<"example"/utf8>>
),
gleam@result:unwrap(_pipe, none)
end,
Mt_examples = parse_string_map(
Value_node,
<<"examples"/utf8>>
),
Mt_encoding = parse_encoding_map(Value_node),
{ok,
gleam@dict:insert(
Acc,
Media_type_name,
{media_type,
Mt_schema,
Mt_example,
Mt_examples,
Mt_encoding}
)}
end
);
_ ->
{ok, Acc}
end
end
);
_ ->
{error,
{missing_field,
<<Context/binary, ".requestBody"/utf8>>,
<<"content"/utf8>>}}
end.
-file("src/oaspec/openapi/parser.gleam", 761).
?DOC(" Parse a request body object.\n").
-spec parse_request_body(yay:node_(), binary()) -> {ok,
oaspec@openapi@spec:request_body()} |
{error, parse_error()}.
parse_request_body(Node, Context) ->
Description = begin
_pipe = yay:extract_optional_string(Node, <<"description"/utf8>>),
gleam@result:unwrap(_pipe, none)
end,
Required = begin
_pipe@1 = yay:extract_optional_bool(Node, <<"required"/utf8>>),
_pipe@2 = gleam@result:unwrap(_pipe@1, none),
gleam@option:unwrap(_pipe@2, false)
end,
gleam@result:'try'(
parse_required_content(Node, Context),
fun(Content) -> {ok, {request_body, Description, Content, Required}} end
).
-file("src/oaspec/openapi/parser.gleam", 741).
?DOC(" Parse requestBody from a node.\n").
-spec parse_request_body_at(
yay:node_(),
binary(),
gleam@option:option(oaspec@openapi@spec:components())
) -> {ok, oaspec@openapi@spec:request_body()} | {error, parse_error()}.
parse_request_body_at(Node, Context, Components) ->
gleam@result:'try'(
begin
_pipe = yay:select_sugar(Node, <<"requestBody"/utf8>>),
gleam@result:map_error(
_pipe,
fun(_) -> {missing_field, Context, <<"requestBody"/utf8>>} end
)
end,
fun(Rb_node) ->
case yay:extract_optional_string(Rb_node, <<"$ref"/utf8>>) of
{ok, {some, Ref_str}} ->
resolve_request_body_ref(Ref_str, Components);
_ ->
parse_request_body(Rb_node, Context)
end
end
).
-file("src/oaspec/openapi/parser.gleam", 426).
?DOC(
" Parse optional requestBody: Ok(None) if absent, Ok(Some(..)) if valid,\n"
" Error if present but malformed.\n"
).
-spec parse_optional_request_body(
yay:node_(),
binary(),
gleam@option:option(oaspec@openapi@spec:components())
) -> {ok, gleam@option:option(oaspec@openapi@spec:request_body())} |
{error, parse_error()}.
parse_optional_request_body(Node, Context, Components) ->
case yay:select_sugar(Node, <<"requestBody"/utf8>>) of
{ok, _} ->
gleam@result:'try'(
parse_request_body_at(Node, Context, Components),
fun(Rb) -> {ok, {some, Rb}} end
);
{error, _} ->
{ok, none}
end.
-file("src/oaspec/openapi/parser.gleam", 828).
?DOC(" Parse content map (media type -> schema).\n").
-spec parse_content(yay:node_(), binary()) -> {ok,
gleam@dict:dict(binary(), oaspec@openapi@spec:media_type())} |
{error, parse_error()}.
parse_content(Node, Context) ->
case yay:select_sugar(Node, <<"content"/utf8>>) of
{ok, {node_map, Entries}} ->
gleam@list:try_fold(
Entries,
maps:new(),
fun(Acc, Entry) ->
{Key_node, Value_node} = Entry,
case Key_node of
{node_str, Media_type_name} ->
gleam@result:'try'(
case yay:select_sugar(
Value_node,
<<"schema"/utf8>>
) of
{ok, Schema_node} ->
gleam@result:'try'(
parse_schema_ref(
Schema_node,
<<Context/binary,
".schema"/utf8>>
),
fun(Sr) -> {ok, {some, Sr}} end
);
_ ->
{ok, none}
end,
fun(Mt_schema) ->
Mt_example = begin
_pipe = yay:extract_optional_string(
Value_node,
<<"example"/utf8>>
),
gleam@result:unwrap(_pipe, none)
end,
Mt_examples = parse_string_map(
Value_node,
<<"examples"/utf8>>
),
Mt_encoding = parse_encoding_map(Value_node),
{ok,
gleam@dict:insert(
Acc,
Media_type_name,
{media_type,
Mt_schema,
Mt_example,
Mt_examples,
Mt_encoding}
)}
end
);
_ ->
{ok, Acc}
end
end
);
_ ->
{ok, maps:new()}
end.
-file("src/oaspec/openapi/parser.gleam", 964).
?DOC(" Parse the schemas map from components.\n").
-spec parse_schemas_map(yay:node_()) -> {ok,
gleam@dict:dict(binary(), oaspec@openapi@schema:schema_ref())} |
{error, parse_error()}.
parse_schemas_map(Components_node) ->
case yay:select_sugar(Components_node, <<"schemas"/utf8>>) of
{ok, {node_map, Entries}} ->
gleam@list:try_fold(
Entries,
maps:new(),
fun(Acc, Entry) ->
{Key_node, Value_node} = Entry,
case Key_node of
{node_str, Name} ->
gleam@result:'try'(
parse_schema_ref(
Value_node,
<<"components.schemas."/utf8, Name/binary>>
),
fun(Schema_ref) ->
{ok,
gleam@dict:insert(Acc, Name, Schema_ref)}
end
);
_ ->
{ok, Acc}
end
end
);
_ ->
{ok, maps:new()}
end.
-file("src/oaspec/openapi/parser.gleam", 1017).
?DOC(" Parse the requestBodies map from components.\n").
-spec parse_request_bodies_map(yay:node_()) -> {ok,
gleam@dict:dict(binary(), oaspec@openapi@spec:request_body())} |
{error, parse_error()}.
parse_request_bodies_map(Components_node) ->
case yay:select_sugar(Components_node, <<"requestBodies"/utf8>>) of
{ok, {node_map, Entries}} ->
gleam@list:try_fold(
Entries,
maps:new(),
fun(Acc, Entry) ->
{Key_node, Value_node} = Entry,
case Key_node of
{node_str, Name} ->
case yay:extract_optional_string(
Value_node,
<<"$ref"/utf8>>
) of
{ok, {some, _}} ->
{ok, Acc};
_ ->
gleam@result:'try'(
parse_request_body(
Value_node,
<<"components.requestBodies."/utf8,
Name/binary>>
),
fun(Rb) ->
{ok,
gleam@dict:insert(Acc, Name, Rb)}
end
)
end;
_ ->
{ok, Acc}
end
end
);
_ ->
{ok, maps:new()}
end.
-file("src/oaspec/openapi/parser.gleam", 2007).
?DOC(" Parse a content map (non-result version for use in Parameter).\n").
-spec parse_content_map(yay:node_()) -> gleam@dict:dict(binary(), oaspec@openapi@spec:media_type()).
parse_content_map(Node) ->
case yay:select_sugar(Node, <<"content"/utf8>>) of
{ok, {node_map, Entries}} ->
gleam@list:fold(
Entries,
maps:new(),
fun(Acc, Entry) ->
{Key_node, Value_node} = Entry,
case Key_node of
{node_str, Media_type_name} ->
Mt_schema = case yay:select_sugar(
Value_node,
<<"schema"/utf8>>
) of
{ok, Schema_node} ->
case parse_schema_ref(
Schema_node,
<<"content.schema"/utf8>>
) of
{ok, Sr} ->
{some, Sr};
_ ->
none
end;
_ ->
none
end,
Mt_example = begin
_pipe = yay:extract_optional_string(
Value_node,
<<"example"/utf8>>
),
gleam@result:unwrap(_pipe, none)
end,
Mt_examples = parse_string_map(
Value_node,
<<"examples"/utf8>>
),
Mt_encoding = parse_encoding_map(Value_node),
gleam@dict:insert(
Acc,
Media_type_name,
{media_type,
Mt_schema,
Mt_example,
Mt_examples,
Mt_encoding}
);
_ ->
Acc
end
end
);
_ ->
maps:new()
end.
-file("src/oaspec/openapi/parser.gleam", 464).
?DOC(" Parse a single parameter.\n").
-spec parse_parameter(
yay:node_(),
gleam@option:option(oaspec@openapi@spec:components())
) -> {ok, oaspec@openapi@spec:parameter()} | {error, parse_error()}.
parse_parameter(Node, Components) ->
case yay:extract_optional_string(Node, <<"$ref"/utf8>>) of
{ok, {some, Ref_str}} ->
resolve_parameter_ref(Ref_str, Components);
_ ->
gleam@result:'try'(
begin
_pipe = yay:extract_string(Node, <<"name"/utf8>>),
gleam@result:map_error(
_pipe,
fun(_) ->
{missing_field,
<<"parameter"/utf8>>,
<<"name"/utf8>>}
end
)
end,
fun(Name) ->
gleam@result:'try'(
begin
_pipe@1 = yay:extract_string(Node, <<"in"/utf8>>),
gleam@result:map_error(
_pipe@1,
fun(_) ->
{missing_field,
<<"parameter."/utf8, Name/binary>>,
<<"in"/utf8>>}
end
)
end,
fun(In_str) ->
gleam@result:'try'(
parse_parameter_in(In_str),
fun(In_) ->
Description = begin
_pipe@2 = yay:extract_optional_string(
Node,
<<"description"/utf8>>
),
gleam@result:unwrap(_pipe@2, none)
end,
Explicit_required = begin
_pipe@3 = yay:extract_optional_bool(
Node,
<<"required"/utf8>>
),
gleam@result:unwrap(_pipe@3, none)
end,
gleam@result:'try'(
case {In_, Explicit_required} of
{in_path, {some, false}} ->
{error,
{invalid_value,
<<"parameter."/utf8,
Name/binary>>,
<<"Path parameters must have required: true"/utf8>>}};
{in_path, _} ->
{ok, true};
{_, {some, V}} ->
{ok, V};
{_, none} ->
{ok, false}
end,
fun(Required) ->
Deprecated = begin
_pipe@4 = yay:extract_optional_bool(
Node,
<<"deprecated"/utf8>>
),
_pipe@5 = gleam@result:unwrap(
_pipe@4,
none
),
gleam@option:unwrap(
_pipe@5,
false
)
end,
gleam@result:'try'(
case yay:select_sugar(
Node,
<<"schema"/utf8>>
) of
{ok, Schema_node} ->
gleam@result:'try'(
parse_schema_ref(
Schema_node,
<<"parameter.schema"/utf8>>
),
fun(Sr) ->
{ok, {some, Sr}}
end
);
_ ->
{ok, none}
end,
fun(Param_schema) ->
gleam@result:'try'(
case begin
_pipe@6 = yay:extract_optional_string(
Node,
<<"style"/utf8>>
),
gleam@result:unwrap(
_pipe@6,
none
)
end of
{some, S} ->
gleam@result:'try'(
parse_parameter_style(
S
),
fun(Parsed) ->
{ok,
{some,
Parsed}}
end
);
none ->
{ok, none}
end,
fun(Style) ->
Explode = begin
_pipe@7 = yay:extract_optional_bool(
Node,
<<"explode"/utf8>>
),
gleam@result:unwrap(
_pipe@7,
none
)
end,
Allow_reserved = begin
_pipe@8 = yay:extract_optional_bool(
Node,
<<"allowReserved"/utf8>>
),
_pipe@9 = gleam@result:unwrap(
_pipe@8,
none
),
gleam@option:unwrap(
_pipe@9,
false
)
end,
Content = parse_content_map(
Node
),
Examples = parse_string_map(
Node,
<<"examples"/utf8>>
),
{ok,
{parameter,
Name,
In_,
Description,
Required,
Param_schema,
Style,
Explode,
Deprecated,
Allow_reserved,
Content,
Examples}}
end
)
end
)
end
)
end
)
end
)
end
)
end.
-file("src/oaspec/openapi/parser.gleam", 452).
?DOC(" Parse parameters list from a node.\n").
-spec parse_parameters_list(
yay:node_(),
gleam@option:option(oaspec@openapi@spec:components())
) -> {ok, list(oaspec@openapi@spec:parameter())} | {error, parse_error()}.
parse_parameters_list(Node, Components) ->
case yay:select_sugar(Node, <<"parameters"/utf8>>) of
{ok, {node_seq, Items}} ->
gleam@list:try_map(
Items,
fun(Item) -> parse_parameter(Item, Components) end
);
_ ->
{ok, []}
end.
-file("src/oaspec/openapi/parser.gleam", 988).
?DOC(" Parse the parameters map from components.\n").
-spec parse_parameters_map(yay:node_()) -> {ok,
gleam@dict:dict(binary(), oaspec@openapi@spec:parameter())} |
{error, parse_error()}.
parse_parameters_map(Components_node) ->
case yay:select_sugar(Components_node, <<"parameters"/utf8>>) of
{ok, {node_map, Entries}} ->
gleam@list:try_fold(
Entries,
maps:new(),
fun(Acc, Entry) ->
{Key_node, Value_node} = Entry,
case Key_node of
{node_str, Name} ->
case yay:extract_optional_string(
Value_node,
<<"$ref"/utf8>>
) of
{ok, {some, _}} ->
{ok, Acc};
_ ->
gleam@result:'try'(
parse_parameter(Value_node, none),
fun(Param) ->
{ok,
gleam@dict:insert(
Acc,
Name,
Param
)}
end
)
end;
_ ->
{ok, Acc}
end
end
);
_ ->
{ok, maps:new()}
end.
-file("src/oaspec/openapi/parser.gleam", 2085).
?DOC(" Parse headers map from a node.\n").
-spec parse_headers_map(yay:node_()) -> gleam@dict:dict(binary(), oaspec@openapi@spec:header()).
parse_headers_map(Node) ->
case yay:select_sugar(Node, <<"headers"/utf8>>) of
{ok, {node_map, Entries}} ->
gleam@list:fold(
Entries,
maps:new(),
fun(Acc, Entry) ->
{Key_node, Value_node} = Entry,
case Key_node of
{node_str, Header_name} ->
Description = begin
_pipe = yay:extract_optional_string(
Value_node,
<<"description"/utf8>>
),
gleam@result:unwrap(_pipe, none)
end,
Required = begin
_pipe@1 = yay:extract_optional_bool(
Value_node,
<<"required"/utf8>>
),
_pipe@2 = gleam@result:unwrap(_pipe@1, none),
gleam@option:unwrap(_pipe@2, false)
end,
Hdr_schema = case yay:select_sugar(
Value_node,
<<"schema"/utf8>>
) of
{ok, Schema_node} ->
case parse_schema_ref(
Schema_node,
<<<<"header."/utf8, Header_name/binary>>/binary,
".schema"/utf8>>
) of
{ok, Sr} ->
{some, Sr};
_ ->
none
end;
_ ->
none
end,
gleam@dict:insert(
Acc,
Header_name,
{header, Description, Required, Hdr_schema}
);
_ ->
Acc
end
end
);
_ ->
maps:new()
end.
-file("src/oaspec/openapi/parser.gleam", 907).
?DOC(" Parse a single response object.\n").
-spec parse_response(
yay:node_(),
gleam@option:option(oaspec@openapi@spec:components())
) -> {ok, oaspec@openapi@spec:response()} | {error, parse_error()}.
parse_response(Node, Components) ->
case yay:extract_optional_string(Node, <<"$ref"/utf8>>) of
{ok, {some, Ref_str}} ->
resolve_response_ref(Ref_str, Components);
_ ->
gleam@result:'try'(
begin
_pipe = yay:extract_string(Node, <<"description"/utf8>>),
_pipe@1 = gleam@result:map(
_pipe,
fun(Field@0) -> {some, Field@0} end
),
gleam@result:map_error(
_pipe@1,
fun(_) ->
{missing_field,
<<"response"/utf8>>,
<<"description"/utf8>>}
end
)
end,
fun(Description) ->
gleam@result:'try'(
parse_content(Node, <<"response"/utf8>>),
fun(Content) ->
Headers = parse_headers_map(Node),
Links = parse_links_map(Node),
{ok,
{response, Description, Content, Headers, Links}}
end
)
end
)
end.
-file("src/oaspec/openapi/parser.gleam", 875).
?DOC(" Parse responses object.\n").
-spec parse_responses(
yay:node_(),
binary(),
gleam@option:option(oaspec@openapi@spec:components())
) -> {ok, gleam@dict:dict(binary(), oaspec@openapi@spec:response())} |
{error, parse_error()}.
parse_responses(Node, _, Components) ->
case yay:select_sugar(Node, <<"responses"/utf8>>) of
{ok, {node_map, Entries}} ->
gleam@list:try_fold(
Entries,
maps:new(),
fun(Acc, Entry) ->
{Key_node, Value_node} = Entry,
case Key_node of
{node_str, Status_code} ->
case gleam_stdlib:string_starts_with(
Status_code,
<<"x-"/utf8>>
) of
true ->
{ok, Acc};
false ->
gleam@result:'try'(
parse_response(Value_node, Components),
fun(Resp) ->
{ok,
gleam@dict:insert(
Acc,
Status_code,
Resp
)}
end
)
end;
{node_int, Code} ->
gleam@result:'try'(
parse_response(Value_node, Components),
fun(Resp@1) ->
Code_str = gleam@string:inspect(Code),
{ok,
gleam@dict:insert(Acc, Code_str, Resp@1)}
end
);
_ ->
{ok, Acc}
end
end
);
_ ->
{ok, maps:new()}
end.
-file("src/oaspec/openapi/parser.gleam", 443).
?DOC(
" Parse responses, treating the field as optional.\n"
" OpenAPI 3.x requires responses on operations, but webhook operations\n"
" in the wild often omit them. Validation can catch missing responses.\n"
).
-spec parse_responses_required(
yay:node_(),
binary(),
gleam@option:option(oaspec@openapi@spec:components())
) -> {ok, gleam@dict:dict(binary(), oaspec@openapi@spec:response())} |
{error, parse_error()}.
parse_responses_required(Node, Context, Components) ->
parse_responses(Node, Context, Components).
-file("src/oaspec/openapi/parser.gleam", 1047).
?DOC(" Parse the responses map from components.\n").
-spec parse_responses_map(yay:node_()) -> {ok,
gleam@dict:dict(binary(), oaspec@openapi@spec:response())} |
{error, parse_error()}.
parse_responses_map(Components_node) ->
case yay:select_sugar(Components_node, <<"responses"/utf8>>) of
{ok, {node_map, Entries}} ->
gleam@list:try_fold(
Entries,
maps:new(),
fun(Acc, Entry) ->
{Key_node, Value_node} = Entry,
case Key_node of
{node_str, Name} ->
case yay:extract_optional_string(
Value_node,
<<"$ref"/utf8>>
) of
{ok, {some, _}} ->
{ok, Acc};
_ ->
gleam@result:'try'(
parse_response(Value_node, none),
fun(Resp) ->
{ok,
gleam@dict:insert(
Acc,
Name,
Resp
)}
end
)
end;
_ ->
{ok, Acc}
end
end
);
_ ->
{ok, maps:new()}
end.
-file("src/oaspec/openapi/parser.gleam", 934).
?DOC(" Parse the components section.\n").
-spec parse_components(yay:node_()) -> {ok, oaspec@openapi@spec:components()} |
{error, parse_error()}.
parse_components(Root) ->
gleam@result:'try'(
begin
_pipe = yay:select_sugar(Root, <<"components"/utf8>>),
gleam@result:map_error(
_pipe,
fun(_) ->
{missing_field, <<""/utf8>>, <<"components"/utf8>>}
end
)
end,
fun(Components_node) ->
gleam@result:'try'(
parse_schemas_map(Components_node),
fun(Schemas) ->
gleam@result:'try'(
parse_parameters_map(Components_node),
fun(Parameters) ->
gleam@result:'try'(
parse_request_bodies_map(Components_node),
fun(Request_bodies) ->
gleam@result:'try'(
parse_responses_map(Components_node),
fun(Responses) ->
gleam@result:'try'(
parse_security_schemes_map(
Components_node
),
fun(Security_schemes) ->
gleam@result:'try'(
parse_path_items_map(
Components_node
),
fun(Path_items) ->
Headers = parse_headers_map(
Components_node
),
Examples = parse_string_map(
Components_node,
<<"examples"/utf8>>
),
Links = parse_links_map(
Components_node
),
{ok,
{components,
Schemas,
Parameters,
Request_bodies,
Responses,
Security_schemes,
Path_items,
Headers,
Examples,
Links}}
end
)
end
)
end
)
end
)
end
)
end
)
end
).
-file("src/oaspec/openapi/parser.gleam", 113).
?DOC(
" Parse optional components section.\n"
" Returns Ok(None) if not present, Ok(Some(..)) if valid, Error if malformed.\n"
).
-spec parse_optional_components(yay:node_()) -> {ok,
gleam@option:option(oaspec@openapi@spec:components())} |
{error, parse_error()}.
parse_optional_components(Root) ->
case yay:select_sugar(Root, <<"components"/utf8>>) of
{ok, _} ->
gleam@result:'try'(
parse_components(Root),
fun(Comps) -> {ok, {some, Comps}} end
);
{error, _} ->
{ok, none}
end.
-file("src/oaspec/openapi/parser.gleam", 65).
?DOC(" Parse the root OpenAPI object.\n").
-spec parse_root(yay:node_()) -> {ok, oaspec@openapi@spec:open_api_spec()} |
{error, parse_error()}.
parse_root(Node) ->
gleam@result:'try'(
begin
_pipe = yay:extract_string(Node, <<"openapi"/utf8>>),
_pipe@2 = gleam@result:lazy_or(
_pipe,
fun() -> _pipe@1 = yay:extract_float(Node, <<"openapi"/utf8>>),
gleam@result:map(
_pipe@1,
fun(F) -> case F =:= erlang:float(erlang:trunc(F)) of
true ->
<<(erlang:integer_to_binary(erlang:trunc(F)))/binary,
".0"/utf8>>;
false ->
gleam_stdlib:float_to_string(F)
end end
) end
),
gleam@result:map_error(
_pipe@2,
fun(_) -> {missing_field, <<""/utf8>>, <<"openapi"/utf8>>} end
)
end,
fun(Openapi) ->
gleam@result:'try'(
parse_info(Node),
fun(Info) ->
gleam@result:'try'(
parse_optional_components(Node),
fun(Components) ->
gleam@result:'try'(
parse_paths(Node, Components),
fun(Paths) ->
gleam@result:'try'(
parse_servers(Node),
fun(Servers) ->
gleam@result:'try'(
parse_security_requirements(
Node,
<<""/utf8>>
),
fun(Security) ->
gleam@result:'try'(
parse_webhooks(
Node,
Components
),
fun(Webhooks) ->
Tags = parse_tags(
Node
),
External_docs = parse_optional_external_docs(
Node
),
Json_schema_dialect = begin
_pipe@3 = yay:extract_optional_string(
Node,
<<"jsonSchemaDialect"/utf8>>
),
gleam@result:unwrap(
_pipe@3,
none
)
end,
{ok,
{open_api_spec,
Openapi,
Info,
Paths,
Components,
Servers,
Security,
Webhooks,
Tags,
External_docs,
Json_schema_dialect}}
end
)
end
)
end
)
end
)
end
)
end
)
end
).
-file("src/oaspec/openapi/parser.gleam", 49).
?DOC(" Parse an OpenAPI spec from a YAML/JSON string.\n").
-spec parse_string(binary()) -> {ok, oaspec@openapi@spec:open_api_spec()} |
{error, parse_error()}.
parse_string(Content) ->
gleam@result:'try'(
begin
_pipe = yaml_ffi:parse_string(Content),
gleam@result:map_error(
_pipe,
fun(E) -> {yaml_error, yaml_error_to_string(E)} end
)
end,
fun(Docs) -> gleam@result:'try'(case Docs of
[First | _] ->
{ok, First};
[] ->
{error, {yaml_error, <<"Empty document"/utf8>>}}
end, fun(Doc) ->
Root = yay:document_root(Doc),
parse_root(Root)
end) end
).
-file("src/oaspec/openapi/parser.gleam", 37).
?DOC(
" Parse an OpenAPI spec from a file path.\n"
" Supports both YAML (.yaml, .yml) and JSON (.json) files.\n"
).
-spec parse_file(binary()) -> {ok, oaspec@openapi@spec:open_api_spec()} |
{error, parse_error()}.
parse_file(Path) ->
gleam@result:'try'(
begin
_pipe = simplifile:read(Path),
gleam@result:map_error(
_pipe,
fun(_) ->
{file_error, <<"Cannot read file: "/utf8, Path/binary>>}
end
)
end,
fun(Content) -> parse_string(Content) end
).