-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/1, parse_schema_ref/1, 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", 93). ?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, {ok, {info, Title, Description, Version}} end ) end ) end ). -file("src/oaspec/openapi/parser.gleam", 125). ?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, {ok, {server, Url, Description}} end ). -file("src/oaspec/openapi/parser.gleam", 117). ?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", 448). ?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) -> Ref_name = begin _pipe = Ref_str, _pipe@1 = gleam@string:split(_pipe, <<"/"/utf8>>), _pipe@2 = gleam@list:last(_pipe@1), gleam@result:unwrap(_pipe@2, <<"unknown"/utf8>>) end, 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. -file("src/oaspec/openapi/parser.gleam", 477). ?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) -> Ref_name = begin _pipe = Ref_str, _pipe@1 = gleam@string:split(_pipe, <<"/"/utf8>>), _pipe@2 = gleam@list:last(_pipe@1), gleam@result:unwrap(_pipe@2, <<"unknown"/utf8>>) end, 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. -file("src/oaspec/openapi/parser.gleam", 506). ?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) -> Ref_name = begin _pipe = Ref_str, _pipe@1 = gleam@string:split(_pipe, <<"/"/utf8>>), _pipe@2 = gleam@list:last(_pipe@1), gleam@result:unwrap(_pipe@2, <<"unknown"/utf8>>) end, 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. -file("src/oaspec/openapi/parser.gleam", 535). ?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", 956). ?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", 980). ?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} -> <<<<<<"Missing field '"/utf8, Field/binary>>/binary, "' at "/utf8>>/binary, Path/binary>>; {invalid_value, Path@1, Detail@2} -> <<<<<<"Invalid value at "/utf8, Path@1/binary>>/binary, ": "/utf8>>/binary, Detail@2/binary>> end. -file("src/oaspec/openapi/parser.gleam", 1014). ?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 In_str of <<"header"/utf8>> -> {ok, {api_key_scheme, Name, In_str}}; <<"query"/utf8>> -> {ok, {api_key_scheme, Name, In_str}}; <<"cookie"/utf8>> -> {ok, {api_key_scheme, Name, In_str}}; _ -> {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, {ok, {o_auth2_scheme, Description}}; _ -> {error, {invalid_value, <<"securityScheme.type"/utf8>>, <<"Unsupported security scheme type: "/utf8, Type_str/binary>>}} end end ). -file("src/oaspec/openapi/parser.gleam", 993). ?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} -> gleam@result:'try'( parse_security_scheme(Value_node), fun(Scheme) -> {ok, gleam@dict:insert(Acc, Name, Scheme)} end ); _ -> {ok, Acc} end end ); _ -> {ok, maps:new()} end. -file("src/oaspec/openapi/parser.gleam", 1114). ?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, <<<>/binary, Scheme_name/binary>>, <<"Scope must be a string"/utf8>>}} end end ); node_nil -> {ok, []}; _ -> {error, {invalid_value, <<<>/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, <>, <<"Security requirement key must be a string"/utf8>>}} end end ), fun(Scheme_refs) -> {ok, {security_requirement, Scheme_refs}} end ); _ -> {error, {invalid_value, <>, <<"Security requirement must be an object"/utf8>>}} end. -file("src/oaspec/openapi/parser.gleam", 1078). ?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", 1094). ?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", 1165). ?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", 791). ?DOC(" Parse a schema object.\n"). -spec parse_schema_object(yay:node_()) -> {ok, oaspec@openapi@schema:schema_object()} | {error, parse_error()}. parse_schema_object(Node) -> 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, case yay:select_sugar(Node, <<"allOf"/utf8>>) of {ok, {node_seq, Items}} -> gleam@result:'try'( gleam@list:try_map(Items, fun parse_schema_ref/1), fun(Schemas) -> {ok, {all_of_schema, Description, 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 parse_schema_ref/1), 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, Description, 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 parse_schema_ref/1 ), fun(Schemas@2) -> {ok, {any_of_schema, Description, Schemas@2}} end ); _ -> parse_typed_schema(Node, Description, Nullable) end end end. -file("src/oaspec/openapi/parser.gleam", 835). ?DOC(" Parse a typed schema (string, integer, number, boolean, array, object).\n"). -spec parse_typed_schema(yay:node_(), gleam@option:option(binary()), boolean()) -> {ok, oaspec@openapi@schema:schema_object()} | {error, parse_error()}. parse_typed_schema(Node, Description, Nullable) -> Type_str = begin _pipe = yay:extract_optional_string(Node, <<"type"/utf8>>), _pipe@1 = gleam@result:unwrap(_pipe, none), gleam@option:unwrap(_pipe@1, <<"object"/utf8>>) end, 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, Description, Format, Enum_values, Min_length, Max_length, Pattern, Nullable}}; <<"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, {ok, {integer_schema, Description, Format, Minimum, Maximum, Nullable}}; <<"number"/utf8>> -> Minimum@1 = begin _pipe@8 = yay:extract_optional_float(Node, <<"minimum"/utf8>>), gleam@result:unwrap(_pipe@8, none) end, Maximum@1 = begin _pipe@9 = yay:extract_optional_float(Node, <<"maximum"/utf8>>), gleam@result:unwrap(_pipe@9, none) end, {ok, {number_schema, Description, Format, Minimum@1, Maximum@1, Nullable}}; <<"boolean"/utf8>> -> {ok, {boolean_schema, Description, Nullable}}; <<"array"/utf8>> -> gleam@result:'try'(case yay:select_sugar(Node, <<"items"/utf8>>) of {ok, Items_node} -> parse_schema_ref(Items_node); _ -> {error, {missing_field, <<"schema(type=array)"/utf8>>, <<"items"/utf8>>}} end, fun(Items) -> Min_items = begin _pipe@10 = yay:extract_optional_int( Node, <<"minItems"/utf8>> ), gleam@result:unwrap(_pipe@10, none) end, Max_items = begin _pipe@11 = yay:extract_optional_int( Node, <<"maxItems"/utf8>> ), gleam@result:unwrap(_pipe@11, none) end, {ok, {array_schema, Description, Items, Min_items, Max_items, Nullable}} end); _ -> gleam@result:'try'( parse_properties(Node), 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), fun(Sr) -> {ok, {{some, Sr}, false}} end ); _ -> {ok, {none, false}} end, fun(_use0) -> {Additional_properties, Additional_properties_untyped} = _use0, {ok, {object_schema, Description, Properties, Required, Additional_properties, Additional_properties_untyped, Nullable}} end ) end ) end. -file("src/oaspec/openapi/parser.gleam", 935). ?DOC(" Parse properties map from an object schema.\n"). -spec parse_properties(yay:node_()) -> {ok, gleam@dict:dict(binary(), oaspec@openapi@schema:schema_ref())} | {error, parse_error()}. parse_properties(Node) -> 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, Name} -> gleam@result:'try'( parse_schema_ref(Value_node), 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", 780). ?DOC(" Parse a schema reference (either $ref or inline schema).\n"). -spec parse_schema_ref(yay:node_()) -> {ok, oaspec@openapi@schema:schema_ref()} | {error, parse_error()}. parse_schema_ref(Node) -> case yay:extract_optional_string(Node, <<"$ref"/utf8>>) of {ok, {some, Ref}} -> {ok, {reference, Ref}}; _ -> gleam@result:'try'( parse_schema_object(Node), fun(Schema_obj) -> {ok, {inline, Schema_obj}} end ) end. -file("src/oaspec/openapi/parser.gleam", 369). ?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 ), fun(Sr) -> {ok, {some, Sr}} end ); _ -> {ok, none} end, fun(Param_schema) -> Style = begin _pipe@6 = yay:extract_optional_string( Node, <<"style"/utf8>> ), gleam@result:unwrap( _pipe@6, none ) end, {ok, {parameter, Name, In_, Description, Required, Param_schema, Style, Deprecated}} end ) end ) end ) end ) end ) end. -file("src/oaspec/openapi/parser.gleam", 357). ?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", 591). ?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, _) -> 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), fun(Sr) -> {ok, {some, Sr}} end ); _ -> {ok, none} end, fun(Mt_schema) -> {ok, gleam@dict:insert( Acc, Media_type_name, {media_type, Mt_schema} )} end ); _ -> {ok, Acc} end end ); _ -> {ok, maps:new()} end. -file("src/oaspec/openapi/parser.gleam", 572). ?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_content(Node, Context), fun(Content) -> {ok, {request_body, Description, Content, Required}} end ). -file("src/oaspec/openapi/parser.gleam", 552). ?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", 330). ?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", 649). ?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); _ -> Description = begin _pipe = yay:extract_optional_string( Node, <<"description"/utf8>> ), gleam@result:unwrap(_pipe, none) end, gleam@result:'try'( parse_content(Node, <<"response"/utf8>>), fun(Content) -> {ok, {response, Description, Content}} end ) end. -file("src/oaspec/openapi/parser.gleam", 621). ?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} -> gleam@result:'try'( parse_response(Value_node, Components), fun(Resp) -> {ok, gleam@dict:insert( Acc, Status_code, Resp )} 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", 345). ?DOC(" Parse responses, requiring the field to be present.\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) -> case yay:select_sugar(Node, <<"responses"/utf8>>) of {ok, _} -> parse_responses(Node, Context, Components); {error, _} -> {error, {missing_field, Context, <<"responses"/utf8>>}} end. -file("src/oaspec/openapi/parser.gleam", 270). ?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) -> {ok, {operation, Operation_id, Summary, Description, Tags, Parameters, Request_body, Responses, Deprecated, Security}} end ) end ) end ) end ). -file("src/oaspec/openapi/parser.gleam", 254). ?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, <<<>/binary, Method_key/binary>>, Components ) end ). -file("src/oaspec/openapi/parser.gleam", 231). ?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", 165). ?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_parameters_list( Node, Components ), fun(Parameters) -> {ok, {path_item, Summary, Description, Get, Post, Put, Delete, Patch, Parameters}} end ) end ) end ) end ) end ) end ). -file("src/oaspec/openapi/parser.gleam", 139). ?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} -> gleam@result:'try'( parse_path_item(Value_node, Path, Components), fun(Path_item) -> {ok, gleam@dict:insert(Acc, Path, Path_item)} end ); _ -> {ok, Acc} end end ); _ -> {ok, maps:new()} end. -file("src/oaspec/openapi/parser.gleam", 691). ?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), 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", 712). ?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} -> gleam@result:'try'( parse_parameter(Value_node, none), fun(Param) -> {ok, gleam@dict:insert(Acc, Name, Param)} end ); _ -> {ok, Acc} end end ); _ -> {ok, maps:new()} end. -file("src/oaspec/openapi/parser.gleam", 734). ?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} -> gleam@result:'try'( parse_request_body( Value_node, <<"components.requestBodies."/utf8, Name/binary>> ), fun(Rb) -> {ok, gleam@dict:insert(Acc, Name, Rb)} end ); _ -> {ok, Acc} end end ); _ -> {ok, maps:new()} end. -file("src/oaspec/openapi/parser.gleam", 758). ?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} -> gleam@result:'try'( parse_response(Value_node, none), fun(Resp) -> {ok, gleam@dict:insert(Acc, Name, Resp)} end ); _ -> {ok, Acc} end end ); _ -> {ok, maps:new()} end. -file("src/oaspec/openapi/parser.gleam", 669). ?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) -> {ok, {components, Schemas, Parameters, Request_bodies, Responses, Security_schemes}} end ) end ) end ) end ) end ) end ). -file("src/oaspec/openapi/parser.gleam", 80). ?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", 59). ?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>>), gleam@result:map_error( _pipe, 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) -> {ok, {open_api_spec, Openapi, Info, Paths, Components, Servers, Security}} end ) end ) end ) end ) end ) end ). -file("src/oaspec/openapi/parser.gleam", 43). ?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", 31). ?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 ).