-module(oaspec@internal@codegen@validate). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/oaspec/internal/codegen/validate.gleam"). -export([errors_only/1, warnings_only/1, filter_by_mode/2, error_to_string/1, validate/1]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC(false). -file("src/oaspec/internal/codegen/validate.gleam", 53). ?DOC(false). -spec validate_decode_list_collisions(oaspec@internal@codegen@context:context()) -> list(oaspec@openapi@diagnostic:diagnostic()). validate_decode_list_collisions(Ctx) -> Schema_names = case erlang:element( 5, oaspec@internal@codegen@context:spec(Ctx) ) of {some, Components} -> _pipe = maps:to_list(erlang:element(2, Components)), gleam@list:map(_pipe, fun(Entry) -> erlang:element(1, Entry) end); none -> [] end, gleam@list:filter_map( Schema_names, fun(Base_name) -> Collider_name = <>, case gleam@list:contains(Schema_names, Collider_name) of false -> {error, nil}; true -> Snake = oaspec@internal@util@naming:to_snake_case(Base_name), {ok, oaspec@openapi@diagnostic:validation( <<"components.schemas."/utf8, Collider_name/binary>>, <<<<<<<<<<<<<<<<<<<<"Schema name '"/utf8, Collider_name/binary>>/binary, "' would generate decode_"/utf8>>/binary, Snake/binary>>/binary, "_list, which collides with the synthetic list decoder for '"/utf8>>/binary, Base_name/binary>>/binary, "' (a JSON array of "/utf8>>/binary, Base_name/binary>>/binary, "). gleam build will fail with `Duplicate definition: decode_"/utf8>>/binary, Snake/binary>>/binary, "_list`."/utf8>>, severity_error, target_both, {some, <<<<<<<<<<<<<<<<"Rename one of the schemas. Example: rename '"/utf8, Collider_name/binary>>/binary, "' to '"/utf8>>/binary, Base_name/binary>>/binary, "Collection', '"/utf8>>/binary, Base_name/binary>>/binary, "Page', or '"/utf8>>/binary, Base_name/binary>>/binary, "Items'."/utf8>>} )} end end ). -file("src/oaspec/internal/codegen/validate.gleam", 141). ?DOC(false). -spec group_operations_by_id( list({binary(), oaspec@internal@openapi@spec:operation(oaspec@internal@openapi@spec:resolved()), binary(), oaspec@internal@openapi@spec:http_method()}), fun((binary()) -> binary()) ) -> gleam@dict:dict(binary(), list(binary())). group_operations_by_id(Operations, Key_fn) -> gleam@list:fold( Operations, maps:new(), fun(Acc, Entry) -> {Op_id, _, Path, Method} = Entry, Key = Key_fn(Op_id), Site = <<<<(string:uppercase( oaspec@internal@openapi@spec:method_to_string(Method) ))/binary, " "/utf8>>/binary, Path/binary>>, case gleam_stdlib:map_get(Acc, Key) of {ok, Existing} -> gleam@dict:insert(Acc, Key, lists:append(Existing, [Site])); {error, _} -> gleam@dict:insert(Acc, Key, [Site]) end end ). -file("src/oaspec/internal/codegen/validate.gleam", 157). ?DOC(false). -spec duplicate_operation_id_diagnostic(binary(), list(binary())) -> oaspec@openapi@diagnostic:diagnostic(). duplicate_operation_id_diagnostic(Op_id, Sites) -> oaspec@openapi@diagnostic:invalid_value( <<"paths.*.operationId"/utf8>>, <<<<<<<<<<"Duplicate operationId '"/utf8, Op_id/binary>>/binary, "' found on: "/utf8>>/binary, (gleam@string:join(Sites, <<", "/utf8>>))/binary>>/binary, ". operationId must be unique across the entire spec; "/utf8>>/binary, "rename one of the operations to keep the generated API stable."/utf8>>, no_source_loc ). -file("src/oaspec/internal/codegen/validate.gleam", 173). ?DOC(false). -spec duplicate_function_name_diagnostic(binary(), list(binary())) -> oaspec@openapi@diagnostic:diagnostic(). duplicate_function_name_diagnostic(Fn_name, Sites) -> oaspec@openapi@diagnostic:invalid_value( <<"paths.*.operationId"/utf8>>, <<<<<<<<<<"operationIds that normalize to the same generated function name '"/utf8, Fn_name/binary>>/binary, "' found on: "/utf8>>/binary, (gleam@string:join(Sites, <<", "/utf8>>))/binary>>/binary, ". oaspec converts operationIds to snake_case, so values like "/utf8>>/binary, "'listItems' and 'list_items' collide; rename one of them."/utf8>>, no_source_loc ). -file("src/oaspec/internal/codegen/validate.gleam", 101). ?DOC(false). -spec validate_unique_operation_ids( list({binary(), oaspec@internal@openapi@spec:operation(oaspec@internal@openapi@spec:resolved()), binary(), oaspec@internal@openapi@spec:http_method()}) ) -> list(oaspec@openapi@diagnostic:diagnostic()). validate_unique_operation_ids(Operations) -> Literal = group_operations_by_id(Operations, fun(Op_id) -> Op_id end), By_function = group_operations_by_id( Operations, fun oaspec@internal@util@naming:operation_to_function_name/1 ), Literal_errors = begin _pipe = maps:to_list(Literal), gleam@list:filter_map( _pipe, fun(Entry) -> {Op_id@1, Sites} = Entry, case Sites of [_, _ | _] -> {ok, duplicate_operation_id_diagnostic(Op_id@1, Sites)}; _ -> {error, nil} end end ) end, Function_errors = begin _pipe@1 = maps:to_list(By_function), gleam@list:filter_map( _pipe@1, fun(Entry@1) -> {Fn_name, Sites@1} = Entry@1, case Sites@1 of [_, _ | _] -> case gleam_stdlib:map_get(Literal, Fn_name) of {ok, Literal_sites} when Literal_sites =:= Sites@1 -> {error, nil}; _ -> {ok, duplicate_function_name_diagnostic( Fn_name, Sites@1 )} end; _ -> {error, nil} end end ) end, lists:append(Literal_errors, Function_errors). -file("src/oaspec/internal/codegen/validate.gleam", 190). ?DOC(false). -spec errors_only(list(oaspec@openapi@diagnostic:diagnostic())) -> list(oaspec@openapi@diagnostic:diagnostic()). errors_only(Issues) -> oaspec@openapi@diagnostic:errors_only(Issues). -file("src/oaspec/internal/codegen/validate.gleam", 195). ?DOC(false). -spec warnings_only(list(oaspec@openapi@diagnostic:diagnostic())) -> list(oaspec@openapi@diagnostic:diagnostic()). warnings_only(Issues) -> oaspec@openapi@diagnostic:warnings_only(Issues). -file("src/oaspec/internal/codegen/validate.gleam", 200). ?DOC(false). -spec filter_by_mode( list(oaspec@openapi@diagnostic:diagnostic()), oaspec@config:generate_mode() ) -> list(oaspec@openapi@diagnostic:diagnostic()). filter_by_mode(Issues, Mode) -> oaspec@openapi@diagnostic:filter_by_mode(Issues, Mode). -file("src/oaspec/internal/codegen/validate.gleam", 208). ?DOC(false). -spec error_to_string(oaspec@openapi@diagnostic:diagnostic()) -> binary(). error_to_string(Error) -> oaspec@openapi@diagnostic:to_string(Error). -file("src/oaspec/internal/codegen/validate.gleam", 306). ?DOC(false). -spec extract_path_template_names(binary()) -> list(binary()). extract_path_template_names(Path) -> Re@1 = case gleam@regexp:from_string(<<"\\{([^}]+)\\}"/utf8>>) of {ok, Re} -> Re; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"oaspec/internal/codegen/validate"/utf8>>, function => <<"extract_path_template_names"/utf8>>, line => 308, value => _assert_fail, start => 10877, 'end' => 10932, pattern_start => 10888, pattern_end => 10894}) end, _pipe = gleam@regexp:scan(Re@1, Path), gleam@list:filter_map(_pipe, fun(Match) -> case erlang:element(3, Match) of [{some, Name}] -> {ok, Name}; _ -> {error, nil} end end). -file("src/oaspec/internal/codegen/validate.gleam", 264). ?DOC(false). -spec validate_path_template_params( binary(), binary(), list(oaspec@internal@openapi@spec:parameter(oaspec@internal@openapi@spec:resolved())) ) -> list(oaspec@openapi@diagnostic:diagnostic()). validate_path_template_params(Op_id, Path, Params) -> Template_names = extract_path_template_names(Path), Path_param_names = gleam@list:filter_map( Params, fun(P) -> case erlang:element(3, P) of in_path -> {ok, erlang:element(2, P)}; _ -> {error, nil} end end ), gleam@list:filter_map( Template_names, fun(Name) -> case gleam@list:contains(Path_param_names, Name) of true -> {error, nil}; false -> Defined = case Path_param_names of [] -> <<""/utf8>>; Names -> <<<<" Defined path parameters: "/utf8, (gleam@string:join(Names, <<", "/utf8>>))/binary>>/binary, "."/utf8>> end, {ok, oaspec@openapi@diagnostic:validation( <>, <<<<<<<<"Path template parameter '{"/utf8, Name/binary>>/binary, "}' in '"/utf8>>/binary, Path/binary>>/binary, "' has no corresponding parameter definition."/utf8>>, severity_error, target_both, {some, <<"Add a parameter definition with 'in: path' for this variable, or remove it from the path template."/utf8, Defined/binary>>} )} end end ). -file("src/oaspec/internal/codegen/validate.gleam", 541). ?DOC(false). -spec validate_server_cookie_param( binary(), oaspec@internal@openapi@spec:parameter(oaspec@internal@openapi@spec:resolved()), oaspec@internal@codegen@context:context() ) -> list(oaspec@openapi@diagnostic:diagnostic()). validate_server_cookie_param(_, _, _) -> []. -file("src/oaspec/internal/codegen/validate.gleam", 653). ?DOC(false). -spec resolve_schema_object( gleam@option:option(oaspec@internal@openapi@schema:schema_ref()), oaspec@internal@codegen@context:context() ) -> gleam@option:option(oaspec@internal@openapi@schema:schema_object()). resolve_schema_object(Schema_ref, Ctx) -> case Schema_ref of {some, {inline, Schema_obj}} -> {some, Schema_obj}; {some, Schema_ref@1} -> case oaspec@internal@codegen@context:resolve_schema_ref( Schema_ref@1, Ctx ) of {ok, Schema_obj@1} -> {some, Schema_obj@1}; {error, _} -> none end; none -> none end. -file("src/oaspec/internal/codegen/validate.gleam", 382). ?DOC(false). -spec validate_delimited_style( binary(), oaspec@internal@openapi@spec:parameter(oaspec@internal@openapi@spec:resolved()), binary(), oaspec@internal@codegen@context:context() ) -> list(oaspec@openapi@diagnostic:diagnostic()). validate_delimited_style(Path, Param, Style_name, Ctx) -> Location_errors = case erlang:element(3, Param) of in_query -> []; _ -> [oaspec@openapi@diagnostic:validation( Path, <<<<"Parameter style '"/utf8, Style_name/binary>>/binary, "' is only supported for 'in: query'."/utf8>>, severity_error, target_both, {some, <<"Move this parameter to 'in: query' or switch to a style valid for its location."/utf8>>} )] end, Schema_errors = case resolve_schema_object( oaspec@internal@openapi@spec:parameter_schema(Param), Ctx ) of {some, {array_schema, _, _, _, _, _}} -> []; _ -> [oaspec@openapi@diagnostic:validation( Path, <<<<"Parameter style '"/utf8, Style_name/binary>>/binary, "' requires an array schema."/utf8>>, severity_error, target_both, {some, <<"Change the schema to 'type: array' or switch to style 'form'."/utf8>>} )] end, lists:append([Location_errors, Schema_errors]). -file("src/oaspec/internal/codegen/validate.gleam", 512). ?DOC(false). -spec deep_object_server_leaf_supported( oaspec@internal@openapi@schema:schema_ref(), oaspec@internal@codegen@context:context() ) -> boolean(). deep_object_server_leaf_supported(Schema_ref, Ctx) -> case Schema_ref of {inline, {string_schema, _, _, _, _, _, _}} -> true; {inline, {integer_schema, _, _, _, _, _, _, _}} -> true; {inline, {number_schema, _, _, _, _, _, _, _}} -> true; {inline, {boolean_schema, _}} -> true; {inline, {array_schema, _, {inline, {string_schema, _, _, _, _, _, _}}, _, _, _}} -> true; {inline, {array_schema, _, {inline, {integer_schema, _, _, _, _, _, _, _}}, _, _, _}} -> true; {inline, {array_schema, _, {inline, {number_schema, _, _, _, _, _, _, _}}, _, _, _}} -> true; {inline, {array_schema, _, {inline, {boolean_schema, _}}, _, _, _}} -> true; {reference, _, _} -> case resolve_schema_object({some, Schema_ref}, Ctx) of {some, {string_schema, _, _, _, _, _, _}} -> true; {some, {integer_schema, _, _, _, _, _, _, _}} -> true; {some, {number_schema, _, _, _, _, _, _, _}} -> true; {some, {boolean_schema, _}} -> true; {some, {array_schema, _, {inline, {string_schema, _, _, _, _, _, _}}, _, _, _}} -> true; {some, {array_schema, _, {inline, {integer_schema, _, _, _, _, _, _, _}}, _, _, _}} -> true; {some, {array_schema, _, {inline, {number_schema, _, _, _, _, _, _, _}}, _, _, _}} -> true; {some, {array_schema, _, {inline, {boolean_schema, _}}, _, _, _}} -> true; _ -> false end; _ -> false end. -file("src/oaspec/internal/codegen/validate.gleam", 476). ?DOC(false). -spec validate_server_deep_object_param( binary(), oaspec@internal@openapi@spec:parameter(oaspec@internal@openapi@spec:resolved()), oaspec@internal@codegen@context:context() ) -> list(oaspec@openapi@diagnostic:diagnostic()). validate_server_deep_object_param(Path, Param, Ctx) -> case {erlang:element(3, Param), erlang:element(7, Param), resolve_schema_object( oaspec@internal@openapi@spec:parameter_schema(Param), Ctx )} of {in_query, {some, deep_object_style}, {some, {object_schema, _, Properties, _, _, _, _}}} -> _pipe = maps:to_list(Properties), gleam@list:flat_map( _pipe, fun(Entry) -> {Prop_name, Prop_ref} = Entry, case deep_object_server_leaf_supported(Prop_ref, Ctx) of true -> []; false -> [oaspec@openapi@diagnostic:validation( <<<>/binary, Prop_name/binary>>, <<"deepObject properties are only supported for inline primitive scalars and inline primitive array leaves in server code generation."/utf8>>, severity_error, target_server, {some, <<"Simplify deepObject properties to primitive scalars or primitive arrays."/utf8>>} )] end end ); {_, _, _} -> [] end. -file("src/oaspec/internal/codegen/validate.gleam", 425). ?DOC(false). -spec validate_server_structured_param( binary(), oaspec@internal@openapi@spec:parameter(oaspec@internal@openapi@spec:resolved()), oaspec@internal@codegen@context:context() ) -> list(oaspec@openapi@diagnostic:diagnostic()). validate_server_structured_param(Path, Param, Ctx) -> case oaspec@config:mode(oaspec@internal@codegen@context:config(Ctx)) of client -> []; _ -> Schema_obj = resolve_schema_object( oaspec@internal@openapi@spec:parameter_schema(Param), Ctx ), Array_errors = case {erlang:element(3, Param), Schema_obj} of {in_query, {some, {array_schema, _, {inline, {string_schema, _, _, _, _, _, _}}, _, _, _}}} -> []; {in_query, {some, {array_schema, _, {inline, {integer_schema, _, _, _, _, _, _, _}}, _, _, _}}} -> []; {in_query, {some, {array_schema, _, {inline, {number_schema, _, _, _, _, _, _, _}}, _, _, _}}} -> []; {in_query, {some, {array_schema, _, {inline, {boolean_schema, _}}, _, _, _}}} -> []; {in_query, {some, {array_schema, _, _, _, _, _}}} -> [oaspec@openapi@diagnostic:validation( Path, <<"Query array parameters are only supported for inline primitive items in server code generation."/utf8>>, severity_error, target_server, {some, <<"Use inline primitive items (string, integer, number, boolean) for array query parameters."/utf8>>} )]; {in_header, {some, {array_schema, _, {inline, {string_schema, _, _, _, _, _, _}}, _, _, _}}} -> []; {in_header, {some, {array_schema, _, {inline, {integer_schema, _, _, _, _, _, _, _}}, _, _, _}}} -> []; {in_header, {some, {array_schema, _, {inline, {number_schema, _, _, _, _, _, _, _}}, _, _, _}}} -> []; {in_header, {some, {array_schema, _, {inline, {boolean_schema, _}}, _, _, _}}} -> []; {in_header, {some, {array_schema, _, _, _, _, _}}} -> [oaspec@openapi@diagnostic:validation( Path, <<"Header array parameters are only supported for inline primitive items in server code generation."/utf8>>, severity_error, target_server, {some, <<"Use inline primitive items (string, integer, number, boolean) for array header parameters."/utf8>>} )]; {_, _} -> [] end, Deep_object_errors = validate_server_deep_object_param( Path, Param, Ctx ), lists:append([Array_errors, Deep_object_errors]) end. -file("src/oaspec/internal/codegen/validate.gleam", 621). ?DOC(false). -spec validate_deep_object_no_nested_objects( binary(), oaspec@internal@openapi@spec:parameter(oaspec@internal@openapi@spec:resolved()), oaspec@internal@codegen@context:context() ) -> list(oaspec@openapi@diagnostic:diagnostic()). validate_deep_object_no_nested_objects(Path, Param, Ctx) -> case resolve_schema_object( oaspec@internal@openapi@spec:parameter_schema(Param), Ctx ) of {some, {object_schema, _, Properties, _, _, _, _}} -> _pipe = maps:to_list(Properties), gleam@list:flat_map( _pipe, fun(Entry) -> {Prop_name, Prop_ref} = Entry, case resolve_schema_object({some, Prop_ref}, Ctx) of {some, {object_schema, _, _, _, _, _, _}} -> [oaspec@openapi@diagnostic:validation( <<<>/binary, Prop_name/binary>>, <<"Nested object properties in deepObject parameters are not supported. Only one level of object nesting is supported (e.g., filter[name]=value)."/utf8>>, severity_error, target_both, {some, <<"Flatten the property structure to a single level of nesting."/utf8>>} )]; {some, {all_of_schema, _, _}} -> [oaspec@openapi@diagnostic:validation( <<<>/binary, Prop_name/binary>>, <<"Nested object properties in deepObject parameters are not supported. Only one level of object nesting is supported (e.g., filter[name]=value)."/utf8>>, severity_error, target_both, {some, <<"Flatten the property structure to a single level of nesting."/utf8>>} )]; {some, {one_of_schema, _, _, _}} -> [oaspec@openapi@diagnostic:validation( <<<>/binary, Prop_name/binary>>, <<"Nested object properties in deepObject parameters are not supported. Only one level of object nesting is supported (e.g., filter[name]=value)."/utf8>>, severity_error, target_both, {some, <<"Flatten the property structure to a single level of nesting."/utf8>>} )]; {some, {any_of_schema, _, _, _}} -> [oaspec@openapi@diagnostic:validation( <<<>/binary, Prop_name/binary>>, <<"Nested object properties in deepObject parameters are not supported. Only one level of object nesting is supported (e.g., filter[name]=value)."/utf8>>, severity_error, target_both, {some, <<"Flatten the property structure to a single level of nesting."/utf8>>} )]; _ -> [] end end ); _ -> [] end. -file("src/oaspec/internal/codegen/validate.gleam", 570). ?DOC(false). -spec validate_complex_param_schema( binary(), oaspec@internal@openapi@spec:parameter(oaspec@internal@openapi@spec:resolved()), oaspec@internal@codegen@context:context() ) -> list(oaspec@openapi@diagnostic:diagnostic()). validate_complex_param_schema(Path, Param, Ctx) -> case erlang:element(7, Param) of {some, deep_object_style} -> validate_deep_object_no_nested_objects(Path, Param, Ctx); _ -> case resolve_schema_object( oaspec@internal@openapi@spec:parameter_schema(Param), Ctx ) of {some, {object_schema, _, _, _, _, _, _}} -> case erlang:element(3, Param) of in_path -> case oaspec@config:mode( oaspec@internal@codegen@context:config(Ctx) ) of client -> []; _ -> [oaspec@openapi@diagnostic:validation( Path, <<"Complex path parameters are not supported for server code generation."/utf8>>, severity_error, target_server, {some, <<"Use a simple scalar type (string, integer, number, boolean) for path parameters."/utf8>>} )] end; _ -> [oaspec@openapi@diagnostic:validation( Path, <<"Complex schema (object/oneOf/allOf/anyOf) parameter has no explicit 'style'; falling back to form-style serialization. This works for oneOf-of-primitives and shallow objects but may not match the spec author's intent for deeply nested objects."/utf8>>, severity_warning, target_both, {some, <<"Declare 'style: deepObject' explicitly if the parameter encodes a structured object."/utf8>>} )] end; {some, {all_of_schema, _, _}} -> case erlang:element(3, Param) of in_path -> case oaspec@config:mode( oaspec@internal@codegen@context:config(Ctx) ) of client -> []; _ -> [oaspec@openapi@diagnostic:validation( Path, <<"Complex path parameters are not supported for server code generation."/utf8>>, severity_error, target_server, {some, <<"Use a simple scalar type (string, integer, number, boolean) for path parameters."/utf8>>} )] end; _ -> [oaspec@openapi@diagnostic:validation( Path, <<"Complex schema (object/oneOf/allOf/anyOf) parameter has no explicit 'style'; falling back to form-style serialization. This works for oneOf-of-primitives and shallow objects but may not match the spec author's intent for deeply nested objects."/utf8>>, severity_warning, target_both, {some, <<"Declare 'style: deepObject' explicitly if the parameter encodes a structured object."/utf8>>} )] end; {some, {one_of_schema, _, _, _}} -> case erlang:element(3, Param) of in_path -> case oaspec@config:mode( oaspec@internal@codegen@context:config(Ctx) ) of client -> []; _ -> [oaspec@openapi@diagnostic:validation( Path, <<"Complex path parameters are not supported for server code generation."/utf8>>, severity_error, target_server, {some, <<"Use a simple scalar type (string, integer, number, boolean) for path parameters."/utf8>>} )] end; _ -> [oaspec@openapi@diagnostic:validation( Path, <<"Complex schema (object/oneOf/allOf/anyOf) parameter has no explicit 'style'; falling back to form-style serialization. This works for oneOf-of-primitives and shallow objects but may not match the spec author's intent for deeply nested objects."/utf8>>, severity_warning, target_both, {some, <<"Declare 'style: deepObject' explicitly if the parameter encodes a structured object."/utf8>>} )] end; {some, {any_of_schema, _, _, _}} -> case erlang:element(3, Param) of in_path -> case oaspec@config:mode( oaspec@internal@codegen@context:config(Ctx) ) of client -> []; _ -> [oaspec@openapi@diagnostic:validation( Path, <<"Complex path parameters are not supported for server code generation."/utf8>>, severity_error, target_server, {some, <<"Use a simple scalar type (string, integer, number, boolean) for path parameters."/utf8>>} )] end; _ -> [oaspec@openapi@diagnostic:validation( Path, <<"Complex schema (object/oneOf/allOf/anyOf) parameter has no explicit 'style'; falling back to form-style serialization. This works for oneOf-of-primitives and shallow objects but may not match the spec author's intent for deeply nested objects."/utf8>>, severity_warning, target_both, {some, <<"Declare 'style: deepObject' explicitly if the parameter encodes a structured object."/utf8>>} )] end; _ -> [] end end. -file("src/oaspec/internal/codegen/validate.gleam", 322). ?DOC(false). -spec validate_parameters( binary(), list(oaspec@internal@openapi@spec:parameter(oaspec@internal@openapi@spec:resolved())), oaspec@internal@codegen@context:context() ) -> list(oaspec@openapi@diagnostic:diagnostic()). validate_parameters(Op_id, Params, Ctx) -> gleam@list:flat_map( Params, fun(P) -> Path = <<<>/binary, (erlang:element(2, P))/binary>>, Style_errors = case erlang:element(7, P) of {some, matrix_style} -> [oaspec@openapi@diagnostic:validation( Path, <<"Parameter style is not supported. Supported styles: form, simple, deepObject, pipeDelimited, spaceDelimited."/utf8>>, severity_error, target_both, {some, <<"Use style 'form', 'simple', 'deepObject', 'pipeDelimited', or 'spaceDelimited' instead."/utf8>>} )]; {some, label_style} -> [oaspec@openapi@diagnostic:validation( Path, <<"Parameter style is not supported. Supported styles: form, simple, deepObject, pipeDelimited, spaceDelimited."/utf8>>, severity_error, target_both, {some, <<"Use style 'form', 'simple', 'deepObject', 'pipeDelimited', or 'spaceDelimited' instead."/utf8>>} )]; {some, pipe_delimited_style} -> validate_delimited_style( Path, P, <<"pipeDelimited"/utf8>>, Ctx ); {some, space_delimited_style} -> validate_delimited_style( Path, P, <<"spaceDelimited"/utf8>>, Ctx ); _ -> [] end, Content_errors = case erlang:element(6, P) of {parameter_content, _} -> [oaspec@openapi@diagnostic:validation( Path, <<"Parameters using 'content' instead of 'schema' are not supported."/utf8>>, severity_error, target_both, {some, <<"Replace the 'content' field with a 'schema' field in the parameter definition."/utf8>>} )]; {parameter_schema, _} -> [] end, Complex_schema_errors = validate_complex_param_schema(Path, P, Ctx), Server_structured_param_errors = validate_server_structured_param( Path, P, Ctx ), Cookie_errors = validate_server_cookie_param(Path, P, Ctx), lists:append( [Style_errors, Content_errors, Complex_schema_errors, Server_structured_param_errors, Cookie_errors] ) end ). -file("src/oaspec/internal/codegen/validate.gleam", 798). ?DOC(false). -spec validate_form_urlencoded_schema( binary(), gleam@dict:dict(binary(), oaspec@internal@openapi@spec:media_type()), oaspec@internal@codegen@context:context() ) -> list(oaspec@openapi@diagnostic:diagnostic()). validate_form_urlencoded_schema(Op_id, Content, Ctx) -> case gleam_stdlib:map_get( Content, <<"application/x-www-form-urlencoded"/utf8>> ) of {ok, Media_type} -> case resolve_schema_object(erlang:element(2, Media_type), Ctx) of {some, {object_schema, _, _, _, _, _, _}} -> []; {some, _} -> [oaspec@openapi@diagnostic:validation( <>, <<"application/x-www-form-urlencoded request bodies must use an object schema."/utf8>>, severity_error, target_both, {some, <<"Wrap fields in an object schema with properties for each form field."/utf8>>} )]; none -> [] end; {error, _} -> [] end. -file("src/oaspec/internal/codegen/validate.gleam", 889). ?DOC(false). -spec validate_server_request_body_content_types( binary(), list(binary()), oaspec@internal@codegen@context:context() ) -> list(oaspec@openapi@diagnostic:diagnostic()). validate_server_request_body_content_types(Op_id, Content_keys, Ctx) -> case oaspec@config:mode(oaspec@internal@codegen@context:config(Ctx)) of client -> []; _ -> Non_json_but_supported = gleam@list:filter( Content_keys, fun(Key) -> (((((Key /= <<"application/json"/utf8>>) andalso (Key /= <<"application/x-www-form-urlencoded"/utf8>>)) andalso (Key /= <<"multipart/form-data"/utf8>>)) andalso (Key /= <<"application/octet-stream"/utf8>>)) andalso (Key /= <<"text/plain"/utf8>>)) andalso oaspec@internal@util@content_type:is_supported_request( oaspec@internal@util@content_type:from_string(Key) ) end ), gleam@list:map( Non_json_but_supported, fun(Media_type) -> oaspec@openapi@diagnostic:validation( <>, <<<<"Content type '"/utf8, Media_type/binary>>/binary, "' is not supported for server code generation. Server router only supports application/json request bodies with typed decoding."/utf8>>, severity_error, target_server, {some, <<"Use application/json for typed server request bodies, or multipart/form-data, application/x-www-form-urlencoded, or application/octet-stream for non-JSON payloads."/utf8>>} ) end ) end. -file("src/oaspec/internal/codegen/validate.gleam", 1002). ?DOC(false). -spec form_urlencoded_server_array_item_supported( oaspec@internal@openapi@schema:schema_ref(), oaspec@internal@codegen@context:context() ) -> boolean(). form_urlencoded_server_array_item_supported(Schema_ref, Ctx) -> case resolve_schema_object({some, Schema_ref}, Ctx) of {some, {string_schema, _, _, _, _, _, _}} -> true; {some, {integer_schema, _, _, _, _, _, _, _}} -> true; {some, {number_schema, _, _, _, _, _, _, _}} -> true; {some, {boolean_schema, _}} -> true; _ -> false end. -file("src/oaspec/internal/codegen/validate.gleam", 980). ?DOC(false). -spec form_urlencoded_server_field_supported( oaspec@internal@openapi@schema:schema_ref(), oaspec@internal@codegen@context:context(), integer() ) -> boolean(). form_urlencoded_server_field_supported(Schema_ref, Ctx, Depth) -> case resolve_schema_object({some, Schema_ref}, Ctx) of {some, {string_schema, _, _, _, _, _, _}} -> true; {some, {integer_schema, _, _, _, _, _, _, _}} -> true; {some, {number_schema, _, _, _, _, _, _, _}} -> true; {some, {boolean_schema, _}} -> true; {some, {array_schema, _, Items, _, _, _}} -> form_urlencoded_server_array_item_supported(Items, Ctx); {some, {object_schema, _, Properties, _, _, _, _}} when Depth < 5 -> _pipe = maps:to_list(Properties), gleam@list:all( _pipe, fun(Entry) -> {_, Child_schema} = Entry, form_urlencoded_server_field_supported( Child_schema, Ctx, Depth + 1 ) end ); _ -> false end. -file("src/oaspec/internal/codegen/validate.gleam", 830). ?DOC(false). -spec validate_server_form_urlencoded_request_body( binary(), gleam@dict:dict(binary(), oaspec@internal@openapi@spec:media_type()), list(binary()), oaspec@internal@codegen@context:context() ) -> list(oaspec@openapi@diagnostic:diagnostic()). validate_server_form_urlencoded_request_body(Op_id, Content, Content_keys, Ctx) -> case oaspec@config:mode(oaspec@internal@codegen@context:config(Ctx)) of client -> []; _ -> case gleam_stdlib:map_get( Content, <<"application/x-www-form-urlencoded"/utf8>> ) of {ok, Media_type} -> Content_type_errors = case erlang:length(Content_keys) > 1 of true -> [oaspec@openapi@diagnostic:validation( <>, <<"application/x-www-form-urlencoded request bodies are only supported as the sole request content type for server code generation."/utf8>>, severity_error, target_server, {some, <<"Remove other content type definitions from this operation's request body."/utf8>>} )]; false -> [] end, Field_errors = case resolve_schema_object( erlang:element(2, Media_type), Ctx ) of {some, {object_schema, _, Properties, _, _, _, _}} -> _pipe = maps:to_list(Properties), gleam@list:flat_map( _pipe, fun(Entry) -> {Field_name, Field_schema} = Entry, case form_urlencoded_server_field_supported( Field_schema, Ctx, 0 ) of true -> []; false -> [oaspec@openapi@diagnostic:validation( <<<>/binary, Field_name/binary>>, <<"application/x-www-form-urlencoded server request bodies only support primitive scalars, primitive arrays, and nested objects with primitive leaves (max 5 levels)."/utf8>>, severity_error, target_server, {some, <<"Simplify to primitive scalars, primitive arrays, or shallow nested objects."/utf8>>} )] end end ); _ -> [] end, lists:append(Content_type_errors, Field_errors); {error, _} -> [] end end. -file("src/oaspec/internal/codegen/validate.gleam", 1027). ?DOC(false). -spec multipart_server_array_item_supported( oaspec@internal@openapi@schema:schema_ref(), oaspec@internal@codegen@context:context() ) -> boolean(). multipart_server_array_item_supported(Schema_ref, Ctx) -> case resolve_schema_object({some, Schema_ref}, Ctx) of {some, {string_schema, _, _, _, _, _, _}} -> true; {some, {integer_schema, _, _, _, _, _, _, _}} -> true; {some, {number_schema, _, _, _, _, _, _, _}} -> true; {some, {boolean_schema, _}} -> true; _ -> false end. -file("src/oaspec/internal/codegen/validate.gleam", 1015). ?DOC(false). -spec multipart_server_field_supported( oaspec@internal@openapi@schema:schema_ref(), oaspec@internal@codegen@context:context() ) -> boolean(). multipart_server_field_supported(Schema_ref, Ctx) -> case resolve_schema_object({some, Schema_ref}, Ctx) of {some, {string_schema, _, _, _, _, _, _}} -> true; {some, {integer_schema, _, _, _, _, _, _, _}} -> true; {some, {number_schema, _, _, _, _, _, _, _}} -> true; {some, {boolean_schema, _}} -> true; {some, {array_schema, _, Items, _, _, _}} -> multipart_server_array_item_supported(Items, Ctx); _ -> false end. -file("src/oaspec/internal/codegen/validate.gleam", 923). ?DOC(false). -spec validate_server_multipart_request_body( binary(), gleam@dict:dict(binary(), oaspec@internal@openapi@spec:media_type()), list(binary()), oaspec@internal@codegen@context:context() ) -> list(oaspec@openapi@diagnostic:diagnostic()). validate_server_multipart_request_body(Op_id, Content, Content_keys, Ctx) -> case oaspec@config:mode(oaspec@internal@codegen@context:config(Ctx)) of client -> []; _ -> case gleam_stdlib:map_get(Content, <<"multipart/form-data"/utf8>>) of {ok, Media_type} -> Content_type_errors = case erlang:length(Content_keys) > 1 of true -> [oaspec@openapi@diagnostic:validation( <>, <<"multipart/form-data request bodies are only supported as the sole request content type for server code generation."/utf8>>, severity_error, target_server, {some, <<"Remove other content type definitions from this operation's request body."/utf8>>} )]; false -> [] end, Field_errors = case resolve_schema_object( erlang:element(2, Media_type), Ctx ) of {some, {object_schema, _, Properties, _, _, _, _}} -> _pipe = maps:to_list(Properties), gleam@list:flat_map( _pipe, fun(Entry) -> {Field_name, Field_schema} = Entry, case multipart_server_field_supported( Field_schema, Ctx ) of true -> []; false -> [oaspec@openapi@diagnostic:validation( <<<>/binary, Field_name/binary>>, <<"multipart/form-data server request bodies only support primitive scalar fields."/utf8>>, severity_error, target_server, {some, <<"Use primitive scalar types or arrays of primitive scalars (string, integer, number, boolean) for multipart form fields."/utf8>>} )] end end ); _ -> [] end, lists:append(Content_type_errors, Field_errors); {error, _} -> [] end end. -file("src/oaspec/internal/codegen/validate.gleam", 1040). ?DOC(false). -spec multipart_field_is_stringifiable( oaspec@internal@openapi@schema:schema_ref(), oaspec@internal@codegen@context:context() ) -> boolean(). multipart_field_is_stringifiable(Schema_ref, Ctx) -> case resolve_schema_object({some, Schema_ref}, Ctx) of {some, {string_schema, _, _, _, _, _, _}} -> true; {some, {integer_schema, _, _, _, _, _, _, _}} -> true; {some, {number_schema, _, _, _, _, _, _, _}} -> true; {some, {boolean_schema, _}} -> true; _ -> false end. -file("src/oaspec/internal/codegen/validate.gleam", 751). ?DOC(false). -spec validate_multipart_request_body_fields( binary(), gleam@dict:dict(binary(), oaspec@internal@openapi@spec:media_type()), oaspec@internal@codegen@context:context() ) -> list(oaspec@openapi@diagnostic:diagnostic()). validate_multipart_request_body_fields(Op_id, Content, Ctx) -> case gleam_stdlib:map_get(Content, <<"multipart/form-data"/utf8>>) of {ok, Media_type} -> case resolve_schema_object(erlang:element(2, Media_type), Ctx) of {some, {object_schema, _, Properties, _, _, _, _}} -> _pipe = maps:to_list(Properties), gleam@list:flat_map( _pipe, fun(Entry) -> {Field_name, Field_schema} = Entry, case multipart_field_is_stringifiable( Field_schema, Ctx ) of true -> []; false -> [oaspec@openapi@diagnostic:validation( <<<>/binary, Field_name/binary>>, <<"multipart/form-data fields must be string, integer, number, boolean, binary, or string enums."/utf8>>, severity_error, target_both, {some, <<"Use a primitive scalar type, binary, or string enum for multipart fields."/utf8>>} )] end end ); {some, _} -> [oaspec@openapi@diagnostic:validation( <>, <<"multipart/form-data request bodies must use an object schema."/utf8>>, severity_error, target_both, {some, <<"Wrap fields in an object schema with properties for each form field."/utf8>>} )]; none -> [] end; {error, _} -> [] end. -file("src/oaspec/internal/codegen/validate.gleam", 1096). ?DOC(false). -spec validate_unique_schema_names(oaspec@internal@codegen@context:context()) -> list(oaspec@openapi@diagnostic:diagnostic()). validate_unique_schema_names(Ctx) -> Schemas = case erlang:element(5, oaspec@internal@codegen@context:spec(Ctx)) of {some, Components} -> maps:keys(erlang:element(2, Components)); none -> [] end, By_type_name = gleam@list:fold( Schemas, maps:new(), fun(Acc, Name) -> Key = oaspec@internal@util@naming:schema_to_type_name(Name), case gleam_stdlib:map_get(Acc, Key) of {ok, Existing} -> gleam@dict:insert(Acc, Key, [Name | Existing]); {error, _} -> gleam@dict:insert(Acc, Key, [Name]) end end ), _pipe = maps:to_list(By_type_name), gleam@list:filter_map( _pipe, fun(Entry) -> {Type_name, Names} = Entry, case Names of [_, _ | _] -> {ok, oaspec@openapi@diagnostic:invalid_value( <<"components.schemas"/utf8>>, <<<<<<<<"Schema names "/utf8, (gleam@string:join( gleam@list:map( Names, fun(N) -> <<<<"\""/utf8, N/binary>>/binary, "\""/utf8>> end ), <<", "/utf8>> ))/binary>>/binary, " all map to Gleam type `"/utf8>>/binary, Type_name/binary>>/binary, "` — rename one to avoid the collision"/utf8>>, no_source_loc )}; _ -> {error, nil} end end ). -file("src/oaspec/internal/codegen/validate.gleam", 1150). ?DOC(false). -spec is_url_style_ref(binary()) -> boolean(). is_url_style_ref(Ref) -> gleam_stdlib:string_starts_with(Ref, <<"http://"/utf8>>) orelse gleam_stdlib:string_starts_with( Ref, <<"https://"/utf8>> ). -file("src/oaspec/internal/codegen/validate.gleam", 1274). ?DOC(false). -spec validate_security_schemes( oaspec@internal@codegen@context:context(), list({binary(), oaspec@internal@openapi@spec:operation(oaspec@internal@openapi@spec:resolved()), binary(), oaspec@internal@openapi@spec:http_method()}) ) -> list(oaspec@openapi@diagnostic:diagnostic()). validate_security_schemes(Ctx, Operations) -> Scheme_names = case erlang:element( 5, oaspec@internal@codegen@context:spec(Ctx) ) of {some, Components} -> maps:keys(erlang:element(6, Components)); none -> [] end, Global_errors = gleam@list:flat_map( erlang:element(7, oaspec@internal@codegen@context:spec(Ctx)), fun(Req) -> gleam@list:filter_map( erlang:element(2, Req), fun(Scheme_ref) -> case gleam@list:contains( Scheme_names, erlang:element(2, Scheme_ref) ) of true -> {error, nil}; false -> {ok, oaspec@openapi@diagnostic:validation( <<"security."/utf8, (erlang:element(2, Scheme_ref))/binary>>, <<<<"Security requirement references scheme '"/utf8, (erlang:element(2, Scheme_ref))/binary>>/binary, "' which is not defined in components.securitySchemes."/utf8>>, severity_error, target_both, {some, <<"Add the security scheme definition to components.securitySchemes or fix the scheme name."/utf8>>} )} end end ) end ), Operation_errors = gleam@list:flat_map( Operations, fun(Op) -> {Op_id, Operation, _, _} = Op, case erlang:element(10, Operation) of {some, Reqs} -> gleam@list:flat_map( Reqs, fun(Req@1) -> gleam@list:filter_map( erlang:element(2, Req@1), fun(Scheme_ref@1) -> case gleam@list:contains( Scheme_names, erlang:element(2, Scheme_ref@1) ) of true -> {error, nil}; false -> {ok, oaspec@openapi@diagnostic:validation( <<<>/binary, (erlang:element( 2, Scheme_ref@1 ))/binary>>, <<<<"Security requirement references scheme '"/utf8, (erlang:element( 2, Scheme_ref@1 ))/binary>>/binary, "' which is not defined in components.securitySchemes."/utf8>>, severity_error, target_both, {some, <<"Add the security scheme definition to components.securitySchemes or fix the scheme name."/utf8>>} )} end end ) end ); none -> [] end end ), lists:append(Global_errors, Operation_errors). -file("src/oaspec/internal/codegen/validate.gleam", 1216). ?DOC(false). -spec validate_schema_recursive( binary(), oaspec@internal@openapi@schema:schema_object(), oaspec@internal@codegen@context:context() ) -> list(oaspec@openapi@diagnostic:diagnostic()). validate_schema_recursive(Path, Schema_obj, Ctx) -> case Schema_obj of {object_schema, _, Properties, _, Additional_properties, _, _} -> Ap_errors = [], Typed_ap_errors = case Additional_properties of {typed, Ap_ref} -> validate_schema_ref_recursive( <>, Ap_ref, Ctx ); forbidden -> []; untyped -> []; unspecified -> [] end, Prop_errors = begin _pipe = maps:to_list(Properties), gleam@list:flat_map( _pipe, fun(Entry) -> {Prop_name, Prop_ref} = Entry, Prop_path = <<<>/binary, Prop_name/binary>>, validate_schema_ref_recursive(Prop_path, Prop_ref, Ctx) end ) end, lists:append([Ap_errors, Typed_ap_errors, Prop_errors]); {array_schema, _, Items, _, _, _} -> validate_schema_ref_recursive( <>, Items, Ctx ); {one_of_schema, _, Schemas, _} -> gleam@list:flat_map( Schemas, fun(S_ref) -> validate_schema_ref_recursive( <>, S_ref, Ctx ) end ); {any_of_schema, _, Schemas@1, _} -> gleam@list:flat_map( Schemas@1, fun(S_ref@1) -> validate_schema_ref_recursive( <>, S_ref@1, Ctx ) end ); {all_of_schema, _, Schemas@2} -> gleam@list:flat_map( Schemas@2, fun(S_ref@2) -> validate_schema_ref_recursive( <>, S_ref@2, Ctx ) end ); _ -> [] end. -file("src/oaspec/internal/codegen/validate.gleam", 1155). ?DOC(false). -spec validate_schema_ref_recursive( binary(), oaspec@internal@openapi@schema:schema_ref(), oaspec@internal@codegen@context:context() ) -> list(oaspec@openapi@diagnostic:diagnostic()). validate_schema_ref_recursive(Path, Schema_ref, Ctx) -> case Schema_ref of {reference, Ref, _} -> case gleam_stdlib:string_starts_with(Ref, <<"#/"/utf8>>) of false -> [case is_url_style_ref(Ref) of true -> oaspec@openapi@diagnostic:validation( Path, <<<<"URL-style $ref '"/utf8, Ref/binary>>/binary, "' is not supported. oaspec does not resolve OpenAPI 3.1 / JSON Schema `$id`-backed identifiers — those refs are an explicit boundary."/utf8>>, severity_error, target_both, {some, <<"Rewrite the schema to a local $ref (`#/components/schemas/...`) and drop the `$id` URL, or inline the schema at the use site."/utf8>>} ); false -> oaspec@openapi@diagnostic:validation( Path, <<<<"External $ref '"/utf8, Ref/binary>>/binary, "' is not supported. Only local references (#/components/...) are supported."/utf8>>, severity_error, target_both, {some, <<"Inline the external schema or copy it into #/components/schemas/ and use a local $ref."/utf8>>} ) end]; true -> case oaspec@internal@codegen@context:resolve_schema_ref( Schema_ref, Ctx ) of {ok, _} -> []; {error, _} -> [oaspec@openapi@diagnostic:validation( Path, <<<<"Unresolved schema reference: '"/utf8, Ref/binary>>/binary, "'. The referenced schema does not exist in components."/utf8>>, severity_error, target_both, {some, <<"Verify the schema is defined in components.schemas and the $ref path is spelled correctly."/utf8>>} )] end end; {inline, Schema_obj} -> validate_schema_recursive(Path, Schema_obj, Ctx) end. -file("src/oaspec/internal/codegen/validate.gleam", 670). ?DOC(false). -spec validate_request_body( binary(), gleam@option:option(oaspec@internal@openapi@spec:request_body(oaspec@internal@openapi@spec:resolved())), oaspec@internal@codegen@context:context() ) -> list(oaspec@openapi@diagnostic:diagnostic()). validate_request_body(Op_id, Request_body, Ctx) -> case Request_body of none -> []; {some, Rb} -> Content_keys = maps:keys(erlang:element(3, Rb)), Unsupported = gleam@list:filter( Content_keys, fun(Key) -> not oaspec@internal@util@content_type:is_supported_request( oaspec@internal@util@content_type:from_string(Key) ) end ), Content_type_errors = case Unsupported of [] -> []; [Media_type | _] -> [oaspec@openapi@diagnostic:validation( <>, <<<<"Content type '"/utf8, Media_type/binary>>/binary, "' is not supported. Supported request content types: application/json (and +json suffix types), text/plain, multipart/form-data, application/x-www-form-urlencoded, application/octet-stream."/utf8>>, severity_error, target_both, {some, <<"Use application/json (or a +json suffix type like application/problem+json), text/plain, multipart/form-data, application/x-www-form-urlencoded, or application/octet-stream."/utf8>>} )] end, Schema_errors = begin _pipe = maps:to_list(erlang:element(3, Rb)), gleam@list:flat_map( _pipe, fun(Entry) -> {_, Media_type@1} = Entry, case erlang:element(2, Media_type@1) of {some, Schema_ref} -> validate_schema_ref_recursive( <>, Schema_ref, Ctx ); none -> [] end end ) end, Multipart_field_errors = validate_multipart_request_body_fields( Op_id, erlang:element(3, Rb), Ctx ), Form_urlencoded_errors = validate_form_urlencoded_schema( Op_id, erlang:element(3, Rb), Ctx ), Server_form_urlencoded_errors = validate_server_form_urlencoded_request_body( Op_id, erlang:element(3, Rb), Content_keys, Ctx ), Server_multipart_errors = validate_server_multipart_request_body( Op_id, erlang:element(3, Rb), Content_keys, Ctx ), Server_body_errors = validate_server_request_body_content_types( Op_id, Content_keys, Ctx ), lists:append( [Content_type_errors, Schema_errors, Multipart_field_errors, Form_urlencoded_errors, Server_form_urlencoded_errors, Server_multipart_errors, Server_body_errors] ) end. -file("src/oaspec/internal/codegen/validate.gleam", 1051). ?DOC(false). -spec validate_responses( binary(), gleam@dict:dict(oaspec@internal@util@http:http_status_code(), oaspec@internal@openapi@spec:response(oaspec@internal@openapi@spec:resolved())), oaspec@internal@codegen@context:context() ) -> list(oaspec@openapi@diagnostic:diagnostic()). validate_responses(Op_id, Responses, Ctx) -> Entries = maps:to_list(Responses), gleam@list:flat_map( Entries, fun(Entry) -> {Status_code, Response} = Entry, Content_entries = maps:to_list(erlang:element(3, Response)), gleam@list:flat_map( Content_entries, fun(Ce) -> {Media_type_name, Media_type} = Ce, Path = <<<>/binary, (oaspec@internal@util@http:status_code_to_string( Status_code ))/binary>>, Content_type_errors = case oaspec@internal@util@content_type:is_supported_response( oaspec@internal@util@content_type:from_string( Media_type_name ) ) of true -> []; false -> [oaspec@openapi@diagnostic:validation( Path, <<<<"Response content type '"/utf8, Media_type_name/binary>>/binary, "' is not supported. Supported response content types: application/json (and +json suffix types), text/plain, application/x-ndjson, application/octet-stream, application/xml (and +xml suffix types), text/xml."/utf8>>, severity_error, target_both, {some, <<"Use application/json (or a +json suffix type), text/plain, application/x-ndjson, application/octet-stream, application/xml (or a +xml suffix type), or text/xml."/utf8>>} )] end, Schema_errors = case erlang:element(2, Media_type) of {some, Schema_ref} -> validate_schema_ref_recursive(Path, Schema_ref, Ctx); none -> [] end, lists:append(Content_type_errors, Schema_errors) end ) end ). -file("src/oaspec/internal/codegen/validate.gleam", 213). ?DOC(false). -spec validate_operations( oaspec@internal@codegen@context:context(), list({binary(), oaspec@internal@openapi@spec:operation(oaspec@internal@openapi@spec:resolved()), binary(), oaspec@internal@openapi@spec:http_method()}) ) -> list(oaspec@openapi@diagnostic:diagnostic()). validate_operations(Ctx, Operations) -> gleam@list:flat_map( Operations, fun(Op) -> {Op_id, Operation, Path, _} = Op, Resolved_params = gleam@list:map( erlang:element(6, Operation), fun oaspec@internal@openapi@spec:unwrap_ref/1 ), Resolved_request_body = case erlang:element(7, Operation) of {some, Ref_or} -> {some, oaspec@internal@openapi@spec:unwrap_ref(Ref_or)}; none -> none end, Resolved_responses = begin _pipe = maps:to_list(erlang:element(8, Operation)), _pipe@1 = gleam@list:map( _pipe, fun(Entry) -> {Status_code, Ref_or@1} = Entry, {Status_code, oaspec@internal@openapi@spec:unwrap_ref(Ref_or@1)} end ), maps:from_list(_pipe@1) end, Path_errors = validate_path_template_params( Op_id, Path, Resolved_params ), Param_errors = validate_parameters(Op_id, Resolved_params, Ctx), Body_errors = validate_request_body( Op_id, Resolved_request_body, Ctx ), Response_errors = validate_responses(Op_id, Resolved_responses, Ctx), Missing_responses_errors = case gleam@dict:is_empty( Resolved_responses ) of true -> [oaspec@openapi@diagnostic:validation( Op_id, <<"Operation has no responses defined. OpenAPI 3.x requires at least one response."/utf8>>, severity_error, target_both, {some, <<"Add at least one response (e.g., '200': { description: ok }) to this operation."/utf8>>} )]; false -> [] end, lists:append( [Path_errors, Param_errors, Body_errors, Response_errors, Missing_responses_errors] ) end ). -file("src/oaspec/internal/codegen/validate.gleam", 1130). ?DOC(false). -spec validate_component_schemas(oaspec@internal@codegen@context:context()) -> list(oaspec@openapi@diagnostic:diagnostic()). validate_component_schemas(Ctx) -> Schemas = case erlang:element(5, oaspec@internal@codegen@context:spec(Ctx)) of {some, Components} -> maps:to_list(erlang:element(2, Components)); none -> [] end, gleam@list:flat_map( Schemas, fun(Entry) -> {Name, Schema_ref} = Entry, validate_schema_ref_recursive( <<"components.schemas."/utf8, Name/binary>>, Schema_ref, Ctx ) end ). -file("src/oaspec/internal/codegen/validate.gleam", 27). ?DOC(false). -spec validate(oaspec@internal@codegen@context:context()) -> list(oaspec@openapi@diagnostic:diagnostic()). validate(Ctx) -> Operations = oaspec@internal@codegen@context:operations(Ctx), Op_errors = validate_operations(Ctx, Operations), Opid_errors = validate_unique_operation_ids(Operations), Schema_errors = validate_component_schemas(Ctx), Schema_collision_errors = validate_unique_schema_names(Ctx), Security_errors = validate_security_schemes(Ctx, Operations), List_decoder_errors = validate_decode_list_collisions(Ctx), lists:append( [Op_errors, Opid_errors, Schema_errors, Schema_collision_errors, Security_errors, List_decoder_errors] ).