Packages
oaspec
0.9.0
0.68.0
0.67.0
0.66.0
0.65.0
0.64.0
0.63.0
0.62.0
0.61.0
0.60.0
0.59.0
0.58.1
0.58.0
0.57.0
0.56.0
0.55.0
0.54.0
0.53.0
0.52.0
0.51.0
0.50.0
0.49.0
0.48.0
0.47.0
0.46.0
0.45.0
0.44.0
0.43.0
0.42.0
0.41.0
0.40.0
0.39.0
0.38.0
0.37.0
0.36.0
0.35.0
0.34.0
0.33.0
0.32.0
0.31.0
0.30.0
0.29.0
0.28.0
0.27.0
0.26.0
0.25.0
0.24.0
0.23.0
0.22.0
0.21.0
0.20.0
0.19.0
0.18.0
0.17.0
0.16.0
0.15.0
0.14.0
0.13.0
0.12.0
0.11.0
0.10.0
0.9.0
0.8.0
0.7.0
0.6.3
0.6.1
0.6.0
0.5.0
0.4.0
0.3.0
0.1.3
Generate Gleam code from OpenAPI 3.x specifications
Current section
Files
Jump to
Current section
Files
src/oaspec@openapi@capability_check.erl
-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_preserved/1, 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", 104).
?DOC(" Check security schemes for unsupported types (e.g. mutualTLS).\n").
-spec check_security_schemes(
oaspec@openapi@spec:open_api_spec(oaspec@openapi@spec:resolved())
) -> list(oaspec@openapi@diagnostic:diagnostic()).
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) ->
{Name, Ref_or} = Entry,
case Ref_or of
{value, {unsupported_scheme, Scheme_type}} ->
{ok,
oaspec@openapi@diagnostic:capability(
<<"components.securitySchemes."/utf8,
Name/binary>>,
<<<<"Unsupported security scheme type: '"/utf8,
Scheme_type/binary>>/binary,
"'. Supported types: apiKey, http, oauth2, openIdConnect."/utf8>>,
severity_error,
target_both
)};
_ ->
{error, nil}
end
end
)
end.
-file("src/oaspec/openapi/capability_check.gleam", 130).
?DOC(
" Check for parsed-but-unused AST features, emitting warnings.\n"
" This is the single source of truth for \"parsed but not generated\" diagnostics.\n"
" Requires Context because some checks iterate over resolved operations.\n"
).
-spec check_preserved(oaspec@codegen@context:context()) -> list(oaspec@openapi@diagnostic:diagnostic()).
check_preserved(Ctx) ->
Webhook_warnings = case gleam@dict:is_empty(
erlang:element(8, erlang:element(2, Ctx))
) of
true ->
[];
false ->
[oaspec@openapi@diagnostic:capability(
<<"webhooks"/utf8>>,
<<"Webhooks are parsed but not used by code generation."/utf8>>,
severity_warning,
target_both
)]
end,
Ops = oaspec@openapi@operations:collect_operations(Ctx),
Response_warnings = gleam@list:flat_map(
Ops,
fun(Op) ->
{Op_id, Operation, _, _} = Op,
Entries = maps:to_list(erlang:element(8, Operation)),
gleam@list:flat_map(
Entries,
fun(Entry) ->
{Status_code, Ref_or} = Entry,
case Ref_or of
{value, Response} ->
Base_path = <<<<Op_id/binary, ".responses."/utf8>>/binary,
Status_code/binary>>,
Multi_content_warnings = case {erlang:element(
6,
erlang:element(3, Ctx)
),
erlang:length(
maps:to_list(erlang:element(3, Response))
)} of
{client, _} ->
[];
{_, N} when N > 1 ->
[oaspec@openapi@diagnostic:capability(
<<Base_path/binary,
".content"/utf8>>,
<<"Multiple response content types are not fully supported for server code generation. Generated server responses lose the content-type header."/utf8>>,
severity_warning,
target_server
)];
{_, _} ->
[]
end,
Header_warnings = case gleam@dict:is_empty(
erlang:element(4, Response)
) of
true ->
[];
false ->
[oaspec@openapi@diagnostic:capability(
<<Base_path/binary,
".headers"/utf8>>,
<<"Response headers are parsed but not used by code generation."/utf8>>,
severity_warning,
target_both
)]
end,
Link_warnings = case gleam@dict:is_empty(
erlang:element(5, Response)
) of
true ->
[];
false ->
[oaspec@openapi@diagnostic:capability(
<<Base_path/binary, ".links"/utf8>>,
<<"Response links are parsed but not used by code generation."/utf8>>,
severity_warning,
target_both
)]
end,
Content_entries = maps:to_list(
erlang:element(3, Response)
),
Encoding_warnings = gleam@list:flat_map(
Content_entries,
fun(Ce) ->
{Media_type_name, Media_type} = Ce,
case gleam@dict:is_empty(
erlang:element(5, Media_type)
) of
true ->
[];
false ->
[oaspec@openapi@diagnostic:capability(
<<<<<<Base_path/binary,
"."/utf8>>/binary,
Media_type_name/binary>>/binary,
".encoding"/utf8>>,
<<"MediaType encoding is parsed but not used by code generation."/utf8>>,
severity_warning,
target_both
)]
end
end
),
lists:append(
[Multi_content_warnings,
Header_warnings,
Link_warnings,
Encoding_warnings]
);
_ ->
[]
end
end
)
end
),
External_docs_warnings = case erlang:element(10, erlang:element(2, Ctx)) of
{some, _} ->
[oaspec@openapi@diagnostic:capability(
<<"externalDocs"/utf8>>,
<<"External docs are parsed but not used by code generation."/utf8>>,
severity_warning,
target_both
)];
none ->
[]
end,
Tag_warnings = case gleam@list:is_empty(
erlang:element(9, erlang:element(2, Ctx))
) of
true ->
[];
false ->
[oaspec@openapi@diagnostic:capability(
<<"tags"/utf8>>,
<<"Top-level tags are parsed but not used by code generation."/utf8>>,
severity_warning,
target_both
)]
end,
Operation_server_warnings = gleam@list:flat_map(
Ops,
fun(Op@1) ->
{Op_id@1, Operation@1, _, _} = Op@1,
case gleam@list:is_empty(erlang:element(12, Operation@1)) of
true ->
[];
false ->
[oaspec@openapi@diagnostic:capability(
<<Op_id@1/binary, ".servers"/utf8>>,
<<"Operation-level servers are parsed but client code generation uses only the top-level server URL."/utf8>>,
severity_warning,
target_client
)]
end
end
),
Path_server_warnings = begin
_pipe = maps:to_list(erlang:element(4, erlang:element(2, Ctx))),
gleam@list:flat_map(
_pipe,
fun(Entry@1) ->
{Path, Ref_or@1} = Entry@1,
case Ref_or@1 of
{value, Path_item} ->
case gleam@list:is_empty(erlang:element(13, Path_item)) of
true ->
[];
false ->
[oaspec@openapi@diagnostic:capability(
<<<<"paths."/utf8, Path/binary>>/binary,
".servers"/utf8>>,
<<"Path-level servers are parsed but client code generation uses only the top-level server URL."/utf8>>,
severity_warning,
target_client
)]
end;
_ ->
[]
end
end
)
end,
Component_warnings = case erlang:element(5, erlang:element(2, Ctx)) of
{some, Components} ->
Header_w = case gleam@dict:is_empty(erlang:element(8, Components)) of
true ->
[];
false ->
[oaspec@openapi@diagnostic:capability(
<<"components.headers"/utf8>>,
<<"Component headers are parsed but not used by code generation."/utf8>>,
severity_warning,
target_both
)]
end,
Example_w = case gleam@dict:is_empty(erlang:element(9, Components)) of
true ->
[];
false ->
[oaspec@openapi@diagnostic:capability(
<<"components.examples"/utf8>>,
<<"Component examples are parsed but not used by code generation."/utf8>>,
severity_warning,
target_both
)]
end,
Link_w = case gleam@dict:is_empty(erlang:element(10, Components)) of
true ->
[];
false ->
[oaspec@openapi@diagnostic:capability(
<<"components.links"/utf8>>,
<<"Component links are parsed but not used by code generation."/utf8>>,
severity_warning,
target_both
)]
end,
lists:append([Header_w, Example_w, Link_w]);
none ->
[]
end,
lists:append(
[Webhook_warnings,
Response_warnings,
External_docs_warnings,
Tag_warnings,
Operation_server_warnings,
Path_server_warnings,
Component_warnings]
).
-file("src/oaspec/openapi/capability_check.gleam", 50).
?DOC(" Check a single schema and recurse into children.\n").
-spec check_schema(binary(), oaspec@openapi@schema:schema_object()) -> list(oaspec@openapi@diagnostic:diagnostic()).
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>>),
[oaspec@openapi@diagnostic:capability(
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(
<<<<Path/binary, "."/utf8>>/binary,
(erlang:element(1, E))/binary>>,
erlang:element(2, E)
)
end
)
end,
Ap_errors = case Additional_properties of
{typed, Ap} ->
check_schema_ref(
<<Path/binary, ".additionalProperties"/utf8>>,
Ap
);
_ ->
[]
end,
lists:append(Prop_errors, Ap_errors);
{array_schema, _, Items, _, _, _} ->
check_schema_ref(<<Path/binary, ".items"/utf8>>, Items);
{all_of_schema, _, Schemas} ->
gleam@list:flat_map(
Schemas,
fun(S) ->
check_schema_ref(<<Path/binary, ".allOf"/utf8>>, S)
end
);
{one_of_schema, _, Schemas@1, _} ->
gleam@list:flat_map(
Schemas@1,
fun(S@1) ->
check_schema_ref(<<Path/binary, ".oneOf"/utf8>>, S@1)
end
);
{any_of_schema, _, Schemas@2, _} ->
gleam@list:flat_map(
Schemas@2,
fun(S@2) ->
check_schema_ref(<<Path/binary, ".anyOf"/utf8>>, S@2)
end
);
_ ->
[]
end,
lists:append(Keyword_errors, Child_errors).
-file("src/oaspec/openapi/capability_check.gleam", 42).
?DOC(" Check a SchemaRef recursively for unsupported keywords.\n").
-spec check_schema_ref(binary(), oaspec@openapi@schema:schema_ref()) -> list(oaspec@openapi@diagnostic:diagnostic()).
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", 29).
?DOC(" Check all schemas for unsupported keywords stored during lossless parse.\n").
-spec check_schemas(
oaspec@openapi@spec:open_api_spec(oaspec@openapi@spec:resolved())
) -> list(oaspec@openapi@diagnostic:diagnostic()).
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", 22).
?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:resolved())) -> list(oaspec@openapi@diagnostic:diagnostic()).
check(Spec) ->
Schema_errors = check_schemas(Spec),
Security_errors = check_security_schemes(Spec),
lists:append([Schema_errors, Security_errors]).