-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, <>, <<<<<<<<<<"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, <<<>/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", 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, <<<>/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, <>, <<"url expression"/utf8>>}}; _ -> {ok, {callback, maps:from_list(Parsed_entries)}} end end ); _ -> {error, {missing_field, <>, <<"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, <<<>/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, <> ) 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, <> ) 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, <> ) 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, <>, <<<<"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, <> ); _ -> {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, <> ), 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, <>, <<<<"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, <<<>/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, <> ), 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, <>, <<"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, <> ), 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 ).