Packages
oaspec
0.64.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@internal@openapi@parser_schema.erl
-module(oaspec@internal@openapi@parser_schema).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/oaspec/internal/openapi/parser_schema.gleam").
-export([parse_schema_ref/3]).
-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/openapi/parser_schema.gleam", 158).
?DOC(false).
-spec is_null_branch(yay:node_()) -> boolean().
is_null_branch(Node) ->
case yay:extract_optional_string(Node, <<"$ref"/utf8>>) of
{ok, {some, _}} ->
false;
_ ->
case yay:select_sugar(Node, <<"type"/utf8>>) of
{ok, {node_str, <<"null"/utf8>>}} ->
true;
_ ->
false
end
end.
-file("src/oaspec/internal/openapi/parser_schema.gleam", 175).
?DOC(false).
-spec partition_null_branches(list(yay:node_())) -> {list(yay:node_()),
boolean()}.
partition_null_branches(Items) ->
{Non_null, Has_null} = gleam@list:fold(
Items,
{[], false},
fun(Acc, Item) ->
{Kept, Seen} = Acc,
case is_null_branch(Item) of
true ->
{Kept, true};
false ->
{[Item | Kept], Seen}
end
end
),
{lists:reverse(Non_null), Has_null}.
-file("src/oaspec/internal/openapi/parser_schema.gleam", 190).
?DOC(false).
-spec detect_unsupported_keywords(yay:node_()) -> list(binary()).
detect_unsupported_keywords(Node) ->
Keywords = [<<"$defs"/utf8>>,
<<"prefixItems"/utf8>>,
<<"if"/utf8>>,
<<"then"/utf8>>,
<<"else"/utf8>>,
<<"dependentSchemas"/utf8>>,
<<"unevaluatedProperties"/utf8>>,
<<"unevaluatedItems"/utf8>>,
<<"contentEncoding"/utf8>>,
<<"contentMediaType"/utf8>>,
<<"contentSchema"/utf8>>,
<<"not"/utf8>>],
gleam@list:filter(
Keywords,
fun(Keyword) -> gleam@result:is_ok(yay:select_sugar(Node, Keyword)) end
).
-file("src/oaspec/internal/openapi/parser_schema.gleam", 479).
?DOC(false).
-spec parse_discriminator(
yay:node_(),
oaspec@internal@openapi@location_index:location_index()
) -> {ok, oaspec@internal@openapi@schema:discriminator()} |
{error, oaspec@openapi@diagnostic:diagnostic()}.
parse_discriminator(Node, Index) ->
gleam@result:'try'(
begin
_pipe = yay:select_sugar(Node, <<"discriminator"/utf8>>),
gleam@result:map_error(
_pipe,
fun(_capture) ->
oaspec@internal@openapi@parser_yay_error:missing_field_from_selector(
_capture,
<<"schema"/utf8>>,
<<"discriminator"/utf8>>,
oaspec@internal@openapi@location_index:lookup_field(
Index,
<<"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(_capture@1) ->
oaspec@internal@openapi@parser_yay_error:missing_field_from_extraction(
_capture@1,
<<"discriminator"/utf8>>,
<<"propertyName"/utf8>>,
oaspec@internal@openapi@location_index:lookup_field(
Index,
<<"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/internal/openapi/parser_schema.gleam", 38).
?DOC(false).
-spec parse_schema_object(
yay:node_(),
binary(),
oaspec@internal@openapi@location_index:location_index()
) -> {ok, oaspec@internal@openapi@schema:schema_object()} |
{error, oaspec@openapi@diagnostic:diagnostic()}.
parse_schema_object(Node, Path, Index) ->
Nullable = oaspec@internal@openapi@parser_value:bool_default(
Node,
<<"nullable"/utf8>>,
false
),
Description = oaspec@internal@openapi@parser_value:optional_string(
Node,
<<"description"/utf8>>
),
Deprecated = oaspec@internal@openapi@parser_value:bool_default(
Node,
<<"deprecated"/utf8>>,
false
),
Title = oaspec@internal@openapi@parser_value:optional_string(
Node,
<<"title"/utf8>>
),
Read_only = oaspec@internal@openapi@parser_value:bool_default(
Node,
<<"readOnly"/utf8>>,
false
),
Write_only = oaspec@internal@openapi@parser_value:bool_default(
Node,
<<"writeOnly"/utf8>>,
false
),
Default = oaspec@internal@openapi@parser_value:extract_optional(
Node,
<<"default"/utf8>>
),
Example = oaspec@internal@openapi@parser_value:extract_optional(
Node,
<<"example"/utf8>>
),
Const_value = oaspec@internal@openapi@parser_value:extract_optional(
Node,
<<"const"/utf8>>
),
Unsupported_keywords = detect_unsupported_keywords(Node),
Metadata = {schema_metadata,
Description,
Nullable,
Deprecated,
Title,
Read_only,
Write_only,
Default,
Example,
Const_value,
none,
Unsupported_keywords,
false,
user_authored},
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,
<<Path/binary, ".allOf"/utf8>>,
Index
)
end
),
fun(Schemas) -> {ok, {all_of_schema, Metadata, Schemas}} end
);
_ ->
case yay:select_sugar(Node, <<"oneOf"/utf8>>) of
{ok, {node_seq, Items@1}} ->
{Non_null_items, Has_null} = partition_null_branches(
Items@1
),
Metadata@1 = case Has_null of
true ->
{schema_metadata,
erlang:element(2, Metadata),
true,
erlang:element(4, Metadata),
erlang:element(5, Metadata),
erlang:element(6, Metadata),
erlang:element(7, Metadata),
erlang:element(8, Metadata),
erlang:element(9, Metadata),
erlang:element(10, Metadata),
erlang:element(11, Metadata),
erlang:element(12, Metadata),
erlang:element(13, Metadata),
erlang:element(14, Metadata)};
false ->
Metadata
end,
gleam@result:'try'(
gleam@list:try_map(
Non_null_items,
fun(_capture@1) ->
parse_schema_ref(
_capture@1,
<<Path/binary, ".oneOf"/utf8>>,
Index
)
end
),
fun(Schemas@1) ->
gleam@result:'try'(
case gleam@result:is_ok(
yay:select_sugar(
Node,
<<"discriminator"/utf8>>
)
) of
true ->
gleam@result:'try'(
parse_discriminator(Node, Index),
fun(D) -> {ok, {some, D}} end
);
false ->
{ok, none}
end,
fun(Discriminator) ->
{ok,
{one_of_schema,
Metadata@1,
Schemas@1,
Discriminator}}
end
)
end
);
_ ->
case yay:select_sugar(Node, <<"anyOf"/utf8>>) of
{ok, {node_seq, Items@2}} ->
{Non_null_items@1, Has_null@1} = partition_null_branches(
Items@2
),
Metadata@2 = case Has_null@1 of
true ->
{schema_metadata,
erlang:element(2, Metadata),
true,
erlang:element(4, Metadata),
erlang:element(5, Metadata),
erlang:element(6, Metadata),
erlang:element(7, Metadata),
erlang:element(8, Metadata),
erlang:element(9, Metadata),
erlang:element(10, Metadata),
erlang:element(11, Metadata),
erlang:element(12, Metadata),
erlang:element(13, Metadata),
erlang:element(14, Metadata)};
false ->
Metadata
end,
gleam@result:'try'(
gleam@list:try_map(
Non_null_items@1,
fun(_capture@2) ->
parse_schema_ref(
_capture@2,
<<Path/binary, ".anyOf"/utf8>>,
Index
)
end
),
fun(Schemas@2) ->
gleam@result:'try'(
case gleam@result:is_ok(
yay:select_sugar(
Node,
<<"discriminator"/utf8>>
)
) of
true ->
gleam@result:'try'(
parse_discriminator(
Node,
Index
),
fun(D@1) ->
{ok, {some, D@1}}
end
);
false ->
{ok, none}
end,
fun(Discriminator@1) ->
{ok,
{any_of_schema,
Metadata@2,
Schemas@2,
Discriminator@1}}
end
)
end
);
_ ->
parse_typed_schema(Node, Metadata, Path, Index)
end
end
end.
-file("src/oaspec/internal/openapi/parser_schema.gleam", 202).
?DOC(false).
-spec parse_typed_schema(
yay:node_(),
oaspec@internal@openapi@schema:schema_metadata(),
binary(),
oaspec@internal@openapi@location_index:location_index()
) -> {ok, oaspec@internal@openapi@schema:schema_object()} |
{error, oaspec@openapi@diagnostic:diagnostic()}.
parse_typed_schema(Node, Metadata, Path, Index) ->
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),
erlang:element(10, Metadata),
erlang:element(11, Metadata),
erlang:element(12, Metadata),
erlang:element(13, Metadata),
erlang:element(14, 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),
erlang:element(10, Metadata),
erlang:element(11, Metadata),
erlang:element(12, Metadata),
erlang:element(13, Metadata),
erlang:element(14, Metadata)}}};
_ ->
Updated_meta = {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),
erlang:element(10, Metadata),
{some, Non_null_types},
erlang:element(12, Metadata),
erlang:element(13, Metadata),
erlang:element(14, Metadata)},
Primary = case Non_null_types of
[First | _] ->
First;
[] ->
<<"object"/utf8>>
end,
{ok, {Primary, Updated_meta}}
end;
{ok, {node_str, <<"null"/utf8>>}} ->
{ok,
{<<"object"/utf8>>,
{schema_metadata,
erlang:element(2, Metadata),
true,
erlang:element(4, Metadata),
erlang:element(5, Metadata),
erlang:element(6, Metadata),
erlang:element(7, Metadata),
erlang:element(8, Metadata),
erlang:element(9, Metadata),
erlang:element(10, Metadata),
erlang:element(11, Metadata),
erlang:element(12, Metadata),
erlang:element(13, Metadata),
erlang:element(14, Metadata)}}};
{ok, {node_str, Type_name}} ->
{ok, {Type_name, Metadata}};
_ ->
Type_name@1 = oaspec@internal@openapi@parser_value:string_default(
Node,
<<"type"/utf8>>,
<<"object"/utf8>>
),
{ok, {Type_name@1, Metadata}}
end, fun(_use0) ->
{Type_str, Metadata@1} = _use0,
Format = oaspec@internal@openapi@parser_value:optional_string(
Node,
<<"format"/utf8>>
),
case Type_str of
<<"string"/utf8>> ->
Enum_values = case yay:extract_string_list(
Node,
<<"enum"/utf8>>
) of
{ok, Values} ->
Values;
_ ->
[]
end,
Min_length = oaspec@internal@openapi@parser_value:optional_int(
Node,
<<"minLength"/utf8>>
),
Max_length = oaspec@internal@openapi@parser_value:optional_int(
Node,
<<"maxLength"/utf8>>
),
Pattern = oaspec@internal@openapi@parser_value:optional_string(
Node,
<<"pattern"/utf8>>
),
{ok,
{string_schema,
Metadata@1,
Format,
Enum_values,
Min_length,
Max_length,
Pattern}};
<<"integer"/utf8>> ->
Raw_minimum = oaspec@internal@openapi@parser_value:optional_int(
Node,
<<"minimum"/utf8>>
),
Raw_maximum = oaspec@internal@openapi@parser_value:optional_int(
Node,
<<"maximum"/utf8>>
),
Numeric_excl_min = oaspec@internal@openapi@parser_value:optional_int(
Node,
<<"exclusiveMinimum"/utf8>>
),
Numeric_excl_max = oaspec@internal@openapi@parser_value:optional_int(
Node,
<<"exclusiveMaximum"/utf8>>
),
Bool_excl_min = oaspec@internal@openapi@parser_value:optional_bool(
Node,
<<"exclusiveMinimum"/utf8>>
),
Bool_excl_max = oaspec@internal@openapi@parser_value:optional_bool(
Node,
<<"exclusiveMaximum"/utf8>>
),
{Minimum, Exclusive_minimum} = case {Numeric_excl_min,
Bool_excl_min,
Raw_minimum} of
{{some, _}, _, _} ->
{Raw_minimum, Numeric_excl_min};
{none, {some, true}, {some, _}} ->
{none, Raw_minimum};
{_, _, _} ->
{Raw_minimum, none}
end,
{Maximum, Exclusive_maximum} = case {Numeric_excl_max,
Bool_excl_max,
Raw_maximum} of
{{some, _}, _, _} ->
{Raw_maximum, Numeric_excl_max};
{none, {some, true}, {some, _}} ->
{none, Raw_maximum};
{_, _, _} ->
{Raw_maximum, none}
end,
Multiple_of = oaspec@internal@openapi@parser_value:optional_int(
Node,
<<"multipleOf"/utf8>>
),
{ok,
{integer_schema,
Metadata@1,
Format,
Minimum,
Maximum,
Exclusive_minimum,
Exclusive_maximum,
Multiple_of}};
<<"number"/utf8>> ->
Raw_minimum@1 = oaspec@internal@openapi@parser_value:optional_float(
Node,
<<"minimum"/utf8>>
),
Raw_maximum@1 = oaspec@internal@openapi@parser_value:optional_float(
Node,
<<"maximum"/utf8>>
),
Numeric_excl_min@1 = oaspec@internal@openapi@parser_value:optional_float(
Node,
<<"exclusiveMinimum"/utf8>>
),
Numeric_excl_max@1 = oaspec@internal@openapi@parser_value:optional_float(
Node,
<<"exclusiveMaximum"/utf8>>
),
Bool_excl_min@1 = oaspec@internal@openapi@parser_value:optional_bool(
Node,
<<"exclusiveMinimum"/utf8>>
),
Bool_excl_max@1 = oaspec@internal@openapi@parser_value:optional_bool(
Node,
<<"exclusiveMaximum"/utf8>>
),
{Minimum@1, Exclusive_minimum@1} = case {Numeric_excl_min@1,
Bool_excl_min@1,
Raw_minimum@1} of
{{some, _}, _, _} ->
{Raw_minimum@1, Numeric_excl_min@1};
{none, {some, true}, {some, _}} ->
{none, Raw_minimum@1};
{_, _, _} ->
{Raw_minimum@1, none}
end,
{Maximum@1, Exclusive_maximum@1} = case {Numeric_excl_max@1,
Bool_excl_max@1,
Raw_maximum@1} of
{{some, _}, _, _} ->
{Raw_maximum@1, Numeric_excl_max@1};
{none, {some, true}, {some, _}} ->
{none, Raw_maximum@1};
{_, _, _} ->
{Raw_maximum@1, none}
end,
Multiple_of@1 = oaspec@internal@openapi@parser_value:optional_float(
Node,
<<"multipleOf"/utf8>>
),
{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,
<<Path/binary, ".items"/utf8>>,
Index
);
_ ->
{error,
oaspec@openapi@diagnostic:missing_field(
Path,
<<"items"/utf8>>,
oaspec@internal@openapi@location_index:lookup_field(
Index,
Path,
<<"items"/utf8>>
)
)}
end,
fun(Items) ->
Min_items = oaspec@internal@openapi@parser_value:optional_int(
Node,
<<"minItems"/utf8>>
),
Max_items = oaspec@internal@openapi@parser_value:optional_int(
Node,
<<"maxItems"/utf8>>
),
Unique_items = oaspec@internal@openapi@parser_value:bool_default(
Node,
<<"uniqueItems"/utf8>>,
false
),
{ok,
{array_schema,
Metadata@1,
Items,
Min_items,
Max_items,
Unique_items}}
end
);
<<"object"/utf8>> ->
gleam@result:'try'(
parse_properties(Node, Path, Index),
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, untyped};
{ok, {node_bool, false}} ->
{ok, forbidden};
{ok, Ap_node} ->
gleam@result:'try'(
parse_schema_ref(
Ap_node,
<<Path/binary,
".additionalProperties"/utf8>>,
Index
),
fun(Sr) -> {ok, {typed, Sr}} end
);
_ ->
{ok, unspecified}
end,
fun(Additional_properties) ->
Min_properties = oaspec@internal@openapi@parser_value:optional_int(
Node,
<<"minProperties"/utf8>>
),
Max_properties = oaspec@internal@openapi@parser_value:optional_int(
Node,
<<"maxProperties"/utf8>>
),
{ok,
{object_schema,
Metadata@1,
Properties,
Required,
Additional_properties,
Min_properties,
Max_properties}}
end
)
end
);
Unrecognized ->
{error,
oaspec@openapi@diagnostic:invalid_value(
<<Path/binary, ".type"/utf8>>,
<<<<"Unrecognized schema type '"/utf8,
Unrecognized/binary>>/binary,
"'. Supported types: string, integer, number, boolean, array, object."/utf8>>,
oaspec@internal@openapi@location_index:lookup(
Index,
<<Path/binary, ".type"/utf8>>
)
)}
end
end).
-file("src/oaspec/internal/openapi/parser_schema.gleam", 452).
?DOC(false).
-spec parse_properties(
yay:node_(),
binary(),
oaspec@internal@openapi@location_index:location_index()
) -> {ok,
gleam@dict:dict(binary(), oaspec@internal@openapi@schema:schema_ref())} |
{error, oaspec@openapi@diagnostic:diagnostic()}.
parse_properties(Node, Path, Index) ->
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,
<<<<Path/binary, "."/utf8>>/binary,
Prop_name/binary>>,
Index
),
fun(Schema_ref) ->
{ok,
gleam@dict:insert(
Acc,
Prop_name,
Schema_ref
)}
end
);
_ ->
{ok, Acc}
end
end
);
_ ->
{ok, maps:new()}
end.
-file("src/oaspec/internal/openapi/parser_schema.gleam", 23).
?DOC(false).
-spec parse_schema_ref(
yay:node_(),
binary(),
oaspec@internal@openapi@location_index:location_index()
) -> {ok, oaspec@internal@openapi@schema:schema_ref()} |
{error, oaspec@openapi@diagnostic:diagnostic()}.
parse_schema_ref(Node, Path, Index) ->
case yay:extract_optional_string(Node, <<"$ref"/utf8>>) of
{ok, {some, Ref}} ->
{ok, oaspec@internal@openapi@schema:make_reference(Ref)};
_ ->
gleam@result:'try'(
parse_schema_object(Node, Path, Index),
fun(Schema_obj) -> {ok, {inline, Schema_obj}} end
)
end.