-module(oaspec@openapi@capability_check). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/oaspec/openapi/capability_check.gleam"). -export([check/1]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. -file("src/oaspec/openapi/capability_check.gleam", 102). ?DOC(" Check security schemes for unsupported types (e.g. mutualTLS).\n"). -spec check_security_schemes( oaspec@openapi@spec:open_api_spec(oaspec@openapi@spec:spec_stage()) ) -> list(oaspec@codegen@validate:validation_error()). check_security_schemes(Spec) -> case erlang:element(5, Spec) of none -> []; {some, Components} -> _pipe = maps:to_list(erlang:element(6, Components)), gleam@list:filter_map( _pipe, fun(Entry) -> {_, Ref_or} = Entry, case Ref_or of {value, _} -> {error, nil}; _ -> {error, nil} end end ) end. -file("src/oaspec/openapi/capability_check.gleam", 123). ?DOC(" Check for parsed-but-unused features using the capability registry.\n"). -spec check_scope( oaspec@openapi@spec:open_api_spec(oaspec@openapi@spec:spec_stage()) ) -> list(oaspec@codegen@validate:validation_error()). check_scope(Spec) -> Webhook_w = case gleam@dict:is_empty(erlang:element(8, Spec)) of true -> []; false -> [{validation_error, <<"webhooks"/utf8>>, <<"Webhooks are parsed but not used by code generation."/utf8>>, severity_warning, target_both}] end, External_docs_w = case erlang:element(10, Spec) of {some, _} -> [{validation_error, <<"externalDocs"/utf8>>, <<"External docs are parsed but not used by code generation."/utf8>>, severity_warning, target_both}]; none -> [] end, Tags_w = case gleam@list:is_empty(erlang:element(9, Spec)) of true -> []; false -> [{validation_error, <<"tags"/utf8>>, <<"Top-level tags are parsed but not used by code generation."/utf8>>, severity_warning, target_both}] end, Server_w = begin _pipe = maps:to_list(erlang:element(4, Spec)), gleam@list:flat_map( _pipe, fun(Entry) -> {Path, Ref_or} = Entry, case Ref_or of {value, Path_item} -> Path_w = case gleam@list:is_empty( erlang:element(13, Path_item) ) of true -> []; false -> [{validation_error, <<<<"paths."/utf8, Path/binary>>/binary, ".servers"/utf8>>, <<"Path-level servers are parsed but client uses only top-level server URL."/utf8>>, severity_warning, target_client}] end, Path_w; _ -> [] end end ) end, Comp_w = case erlang:element(5, Spec) of {some, C} -> H = case gleam@dict:is_empty(erlang:element(8, C)) of true -> []; false -> [{validation_error, <<"components.headers"/utf8>>, <<"Component headers are parsed but not used by code generation."/utf8>>, severity_warning, target_both}] end, L = case gleam@dict:is_empty(erlang:element(10, C)) of true -> []; false -> [{validation_error, <<"components.links"/utf8>>, <<"Component links are parsed but not used by code generation."/utf8>>, severity_warning, target_both}] end, lists:append(H, L); none -> [] end, lists:append([Webhook_w, External_docs_w, Tags_w, Server_w, Comp_w]). -file("src/oaspec/openapi/capability_check.gleam", 48). ?DOC(" Check a single schema and recurse into children.\n"). -spec check_schema(binary(), oaspec@openapi@schema:schema_object()) -> list(oaspec@codegen@validate:validation_error()). check_schema(Path, Schema_obj) -> Metadata = oaspec@openapi@schema:get_metadata(Schema_obj), Keyword_errors = case erlang:element(12, Metadata) of [] -> []; Keywords -> Keyword_list = gleam@string:join(Keywords, <<"', '"/utf8>>), [{validation_error, Path, <<<<<<"Unsupported JSON Schema keyword '"/utf8, Keyword_list/binary>>/binary, "' found. Remove or model differently. See: "/utf8>>/binary, (gleam@string:join( gleam@list:filter_map( Keywords, fun(K) -> _pipe = gleam@list:find( oaspec@capability:registry(), fun(C) -> erlang:element(2, C) =:= K end ), gleam@result:map( _pipe, fun(C@1) -> erlang:element(5, C@1) end ) end ), <<"; "/utf8>> ))/binary>>, severity_error, target_both}] end, Child_errors = case Schema_obj of {object_schema, _, Properties, _, Additional_properties, _, _, _} -> Prop_errors = begin _pipe@1 = maps:to_list(Properties), gleam@list:flat_map( _pipe@1, fun(E) -> check_schema_ref( <<<>/binary, (erlang:element(1, E))/binary>>, erlang:element(2, E) ) end ) end, Ap_errors = case Additional_properties of {some, Ap} -> check_schema_ref( <>, Ap ); none -> [] end, lists:append(Prop_errors, Ap_errors); {array_schema, _, Items, _, _, _} -> check_schema_ref(<>, Items); {all_of_schema, _, Schemas} -> gleam@list:flat_map( Schemas, fun(S) -> check_schema_ref(<>, S) end ); {one_of_schema, _, Schemas@1, _} -> gleam@list:flat_map( Schemas@1, fun(S@1) -> check_schema_ref(<>, S@1) end ); {any_of_schema, _, Schemas@2, _} -> gleam@list:flat_map( Schemas@2, fun(S@2) -> check_schema_ref(<>, S@2) end ); _ -> [] end, lists:append(Keyword_errors, Child_errors). -file("src/oaspec/openapi/capability_check.gleam", 40). ?DOC(" Check a SchemaRef recursively for unsupported keywords.\n"). -spec check_schema_ref(binary(), oaspec@openapi@schema:schema_ref()) -> list(oaspec@codegen@validate:validation_error()). check_schema_ref(Path, Ref) -> case Ref of {reference, _, _} -> []; {inline, Schema_obj} -> check_schema(Path, Schema_obj) end. -file("src/oaspec/openapi/capability_check.gleam", 27). ?DOC(" Check all schemas for unsupported keywords stored during lossless parse.\n"). -spec check_schemas( oaspec@openapi@spec:open_api_spec(oaspec@openapi@spec:spec_stage()) ) -> list(oaspec@codegen@validate:validation_error()). check_schemas(Spec) -> case erlang:element(5, Spec) of none -> []; {some, Components} -> _pipe = maps:to_list(erlang:element(2, Components)), gleam@list:flat_map( _pipe, fun(Entry) -> {Name, Schema_ref} = Entry, check_schema_ref( <<"components.schemas."/utf8, Name/binary>>, Schema_ref ) end ) end. -file("src/oaspec/openapi/capability_check.gleam", 19). ?DOC( " Run capability checks on a resolved spec.\n" " Returns errors for unsupported features and warnings for parsed-but-unused features.\n" ). -spec check(oaspec@openapi@spec:open_api_spec(oaspec@openapi@spec:spec_stage())) -> list(oaspec@codegen@validate:validation_error()). check(Spec) -> Schema_errors = check_schemas(Spec), Security_errors = check_security_schemes(Spec), Scope_warnings = check_scope(Spec), lists:append([Schema_errors, Security_errors, Scope_warnings]).