Current section

Files

Jump to
oaspec src oaspec@codegen@guards.erl
Raw

src/oaspec@codegen@guards.erl

-module(oaspec@codegen@guards).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/oaspec/codegen/guards.gleam").
-export([generate/1]).
-export_type([constraint_types/0, merged_props/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 constraint_types() :: {constraint_types,
boolean(),
boolean(),
boolean(),
boolean(),
boolean(),
boolean()}.
-type merged_props() :: {merged_props,
gleam@dict:dict(binary(), oaspec@openapi@schema:schema_ref()),
list(binary())}.
-file("src/oaspec/codegen/guards.gleam", 150).
?DOC(" Collect constraint types from a single schema ref.\n").
-spec collect_schema_constraint_types(
constraint_types(),
oaspec@openapi@schema:schema_ref(),
oaspec@codegen@context:context()
) -> constraint_types().
collect_schema_constraint_types(Acc, Schema_ref, Ctx) ->
Schema = case Schema_ref of
{inline, S} ->
{ok, S};
{reference, _, _} ->
oaspec@openapi@resolver:resolve_schema_ref(
Schema_ref,
erlang:element(2, Ctx)
)
end,
case Schema of
{ok, {string_schema, _, _, _, {some, _}, _, _}} ->
{constraint_types,
true,
erlang:element(3, Acc),
erlang:element(4, Acc),
erlang:element(5, Acc),
erlang:element(6, Acc),
erlang:element(7, Acc)};
{ok, {string_schema, _, _, _, _, {some, _}, _}} ->
{constraint_types,
true,
erlang:element(3, Acc),
erlang:element(4, Acc),
erlang:element(5, Acc),
erlang:element(6, Acc),
erlang:element(7, Acc)};
{ok, {integer_schema, _, _, {some, _}, _, _, _, _}} ->
{constraint_types,
erlang:element(2, Acc),
true,
erlang:element(4, Acc),
erlang:element(5, Acc),
erlang:element(6, Acc),
erlang:element(7, Acc)};
{ok, {integer_schema, _, _, _, {some, _}, _, _, _}} ->
{constraint_types,
erlang:element(2, Acc),
true,
erlang:element(4, Acc),
erlang:element(5, Acc),
erlang:element(6, Acc),
erlang:element(7, Acc)};
{ok, {integer_schema, _, _, _, _, {some, _}, _, _}} ->
{constraint_types,
erlang:element(2, Acc),
true,
erlang:element(4, Acc),
erlang:element(5, Acc),
erlang:element(6, Acc),
erlang:element(7, Acc)};
{ok, {integer_schema, _, _, _, _, _, {some, _}, _}} ->
{constraint_types,
erlang:element(2, Acc),
true,
erlang:element(4, Acc),
erlang:element(5, Acc),
erlang:element(6, Acc),
erlang:element(7, Acc)};
{ok, {integer_schema, _, _, _, _, _, _, {some, _}}} ->
{constraint_types,
erlang:element(2, Acc),
true,
erlang:element(4, Acc),
erlang:element(5, Acc),
erlang:element(6, Acc),
erlang:element(7, Acc)};
{ok, {number_schema, _, _, {some, _}, _, _, _, _}} ->
{constraint_types,
erlang:element(2, Acc),
erlang:element(3, Acc),
true,
erlang:element(5, Acc),
erlang:element(6, Acc),
erlang:element(7, Acc)};
{ok, {number_schema, _, _, _, {some, _}, _, _, _}} ->
{constraint_types,
erlang:element(2, Acc),
erlang:element(3, Acc),
true,
erlang:element(5, Acc),
erlang:element(6, Acc),
erlang:element(7, Acc)};
{ok, {number_schema, _, _, _, _, {some, _}, _, _}} ->
{constraint_types,
erlang:element(2, Acc),
erlang:element(3, Acc),
true,
erlang:element(5, Acc),
erlang:element(6, Acc),
erlang:element(7, Acc)};
{ok, {number_schema, _, _, _, _, _, {some, _}, _}} ->
{constraint_types,
erlang:element(2, Acc),
erlang:element(3, Acc),
true,
erlang:element(5, Acc),
erlang:element(6, Acc),
erlang:element(7, Acc)};
{ok, {number_schema, _, _, _, _, _, _, {some, _}}} ->
{constraint_types,
erlang:element(2, Acc),
erlang:element(3, Acc),
true,
erlang:element(5, Acc),
true,
erlang:element(7, Acc)};
{ok, {array_schema, _, _, {some, _}, _, _}} ->
{constraint_types,
erlang:element(2, Acc),
erlang:element(3, Acc),
erlang:element(4, Acc),
true,
erlang:element(6, Acc),
erlang:element(7, Acc)};
{ok, {array_schema, _, _, _, {some, _}, _}} ->
{constraint_types,
erlang:element(2, Acc),
erlang:element(3, Acc),
erlang:element(4, Acc),
true,
erlang:element(6, Acc),
erlang:element(7, Acc)};
{ok, {array_schema, _, _, _, _, true}} ->
{constraint_types,
erlang:element(2, Acc),
erlang:element(3, Acc),
erlang:element(4, Acc),
true,
erlang:element(6, Acc),
erlang:element(7, Acc)};
{ok, {object_schema, _, _, _, _, _, {some, _}, _}} ->
{constraint_types,
erlang:element(2, Acc),
erlang:element(3, Acc),
erlang:element(4, Acc),
erlang:element(5, Acc),
erlang:element(6, Acc),
true};
{ok, {object_schema, _, _, _, _, _, _, {some, _}}} ->
{constraint_types,
erlang:element(2, Acc),
erlang:element(3, Acc),
erlang:element(4, Acc),
erlang:element(5, Acc),
erlang:element(6, Acc),
true};
{ok, {object_schema, _, Properties, _, _, _, _, _}} ->
_pipe = maps:to_list(Properties),
gleam@list:fold(
_pipe,
Acc,
fun(A, Prop) ->
{_, Prop_ref} = Prop,
collect_schema_constraint_types(A, Prop_ref, Ctx)
end
);
{ok, {all_of_schema, _, Schemas}} ->
gleam@list:fold(
Schemas,
Acc,
fun(A@1, S@1) ->
collect_schema_constraint_types(A@1, S@1, Ctx)
end
);
_ ->
Acc
end.
-file("src/oaspec/codegen/guards.gleam", 135).
?DOC(" Scan all schemas to find which constraint types are present.\n").
-spec collect_constraint_types(
list({binary(), oaspec@openapi@schema:schema_ref()}),
oaspec@codegen@context:context()
) -> constraint_types().
collect_constraint_types(Schemas, Ctx) ->
gleam@list:fold(
Schemas,
{constraint_types, false, false, false, false, false, false},
fun(Acc, Entry) ->
{_, Schema_ref} = Entry,
collect_schema_constraint_types(Acc, Schema_ref, Ctx)
end
).
-file("src/oaspec/codegen/guards.gleam", 1015).
?DOC(" Build the guard function name from schema name, property name, and constraint type.\n").
-spec guard_function_name(binary(), binary(), binary()) -> binary().
guard_function_name(Schema_name, Prop_name, Constraint) ->
Base = oaspec@util@naming:to_snake_case(Schema_name),
case Prop_name of
<<""/utf8>> ->
<<<<<<"validate_"/utf8, Base/binary>>/binary, "_"/utf8>>/binary,
Constraint/binary>>;
_ ->
<<<<<<<<<<"validate_"/utf8, Base/binary>>/binary, "_"/utf8>>/binary,
(oaspec@util@naming:to_snake_case(Prop_name))/binary>>/binary,
"_"/utf8>>/binary,
Constraint/binary>>
end.
-file("src/oaspec/codegen/guards.gleam", 1034).
?DOC(" Format a field label for documentation.\n").
-spec field_label(binary()) -> binary().
field_label(Prop_name) ->
case Prop_name of
<<""/utf8>> ->
<<""/utf8>>;
_ ->
<<"."/utf8, Prop_name/binary>>
end.
-file("src/oaspec/codegen/guards.gleam", 378).
?DOC(" Generate a string length validation guard.\n").
-spec generate_string_guard(
gleam@string_tree:string_tree(),
binary(),
binary(),
gleam@option:option(integer()),
gleam@option:option(integer())
) -> gleam@string_tree:string_tree().
generate_string_guard(Sb, Schema_name, Prop_name, Min_length, Max_length) ->
case {Min_length, Max_length} of
{none, none} ->
Sb;
{_, _} ->
Fn_name = guard_function_name(
Schema_name,
Prop_name,
<<"length"/utf8>>
),
Sb@1 = begin
_pipe = Sb,
oaspec@util@string_extra:line(
_pipe,
<<<<<<"/// Validate string length for "/utf8,
Schema_name/binary>>/binary,
(field_label(Prop_name))/binary>>/binary,
"."/utf8>>
)
end,
Sb@2 = begin
_pipe@1 = Sb@1,
oaspec@util@string_extra:line(
_pipe@1,
<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: String) -> Result(String, String) {"/utf8>>
)
end,
Sb@3 = begin
_pipe@2 = Sb@2,
oaspec@util@string_extra:indent(
_pipe@2,
1,
<<"let len = string.length(value)"/utf8>>
)
end,
Sb@4 = case {Min_length, Max_length} of
{{some, Min}, {some, Max}} ->
_pipe@3 = Sb@3,
_pipe@4 = oaspec@util@string_extra:indent(
_pipe@3,
1,
<<<<"case len < "/utf8,
(erlang:integer_to_binary(Min))/binary>>/binary,
" {"/utf8>>
),
_pipe@5 = oaspec@util@string_extra:indent(
_pipe@4,
2,
<<<<"True -> Error(\"must be at least "/utf8,
(erlang:integer_to_binary(Min))/binary>>/binary,
" characters\")"/utf8>>
),
_pipe@6 = oaspec@util@string_extra:indent(
_pipe@5,
2,
<<"False ->"/utf8>>
),
_pipe@7 = oaspec@util@string_extra:indent(
_pipe@6,
3,
<<<<"case len > "/utf8,
(erlang:integer_to_binary(Max))/binary>>/binary,
" {"/utf8>>
),
_pipe@8 = oaspec@util@string_extra:indent(
_pipe@7,
4,
<<<<"True -> Error(\"must be at most "/utf8,
(erlang:integer_to_binary(Max))/binary>>/binary,
" characters\")"/utf8>>
),
_pipe@9 = oaspec@util@string_extra:indent(
_pipe@8,
4,
<<"False -> Ok(value)"/utf8>>
),
_pipe@10 = oaspec@util@string_extra:indent(
_pipe@9,
3,
<<"}"/utf8>>
),
oaspec@util@string_extra:indent(_pipe@10, 1, <<"}"/utf8>>);
{{some, Min@1}, none} ->
_pipe@11 = Sb@3,
_pipe@12 = oaspec@util@string_extra:indent(
_pipe@11,
1,
<<<<"case len < "/utf8,
(erlang:integer_to_binary(Min@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@13 = oaspec@util@string_extra:indent(
_pipe@12,
2,
<<<<"True -> Error(\"must be at least "/utf8,
(erlang:integer_to_binary(Min@1))/binary>>/binary,
" characters\")"/utf8>>
),
_pipe@14 = oaspec@util@string_extra:indent(
_pipe@13,
2,
<<"False -> Ok(value)"/utf8>>
),
oaspec@util@string_extra:indent(_pipe@14, 1, <<"}"/utf8>>);
{none, {some, Max@1}} ->
_pipe@15 = Sb@3,
_pipe@16 = oaspec@util@string_extra:indent(
_pipe@15,
1,
<<<<"case len > "/utf8,
(erlang:integer_to_binary(Max@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@17 = oaspec@util@string_extra:indent(
_pipe@16,
2,
<<<<"True -> Error(\"must be at most "/utf8,
(erlang:integer_to_binary(Max@1))/binary>>/binary,
" characters\")"/utf8>>
),
_pipe@18 = oaspec@util@string_extra:indent(
_pipe@17,
2,
<<"False -> Ok(value)"/utf8>>
),
oaspec@util@string_extra:indent(_pipe@18, 1, <<"}"/utf8>>);
{none, none} ->
Sb@3
end,
_pipe@19 = Sb@4,
_pipe@20 = oaspec@util@string_extra:line(_pipe@19, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@20)
end.
-file("src/oaspec/codegen/guards.gleam", 456).
?DOC(" Generate an integer range validation guard.\n").
-spec generate_integer_guard(
gleam@string_tree:string_tree(),
binary(),
binary(),
gleam@option:option(integer()),
gleam@option:option(integer())
) -> gleam@string_tree:string_tree().
generate_integer_guard(Sb, Schema_name, Prop_name, Minimum, Maximum) ->
case {Minimum, Maximum} of
{none, none} ->
Sb;
{_, _} ->
Fn_name = guard_function_name(
Schema_name,
Prop_name,
<<"range"/utf8>>
),
Sb@1 = begin
_pipe = Sb,
oaspec@util@string_extra:line(
_pipe,
<<<<<<"/// Validate integer range for "/utf8,
Schema_name/binary>>/binary,
(field_label(Prop_name))/binary>>/binary,
"."/utf8>>
)
end,
Sb@2 = begin
_pipe@1 = Sb@1,
oaspec@util@string_extra:line(
_pipe@1,
<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: Int) -> Result(Int, String) {"/utf8>>
)
end,
Sb@3 = case {Minimum, Maximum} of
{{some, Min}, {some, Max}} ->
_pipe@2 = Sb@2,
_pipe@3 = oaspec@util@string_extra:indent(
_pipe@2,
1,
<<<<"case value < "/utf8,
(erlang:integer_to_binary(Min))/binary>>/binary,
" {"/utf8>>
),
_pipe@4 = oaspec@util@string_extra:indent(
_pipe@3,
2,
<<<<"True -> Error(\"must be at least "/utf8,
(erlang:integer_to_binary(Min))/binary>>/binary,
"\")"/utf8>>
),
_pipe@5 = oaspec@util@string_extra:indent(
_pipe@4,
2,
<<"False ->"/utf8>>
),
_pipe@6 = oaspec@util@string_extra:indent(
_pipe@5,
3,
<<<<"case value > "/utf8,
(erlang:integer_to_binary(Max))/binary>>/binary,
" {"/utf8>>
),
_pipe@7 = oaspec@util@string_extra:indent(
_pipe@6,
4,
<<<<"True -> Error(\"must be at most "/utf8,
(erlang:integer_to_binary(Max))/binary>>/binary,
"\")"/utf8>>
),
_pipe@8 = oaspec@util@string_extra:indent(
_pipe@7,
4,
<<"False -> Ok(value)"/utf8>>
),
_pipe@9 = oaspec@util@string_extra:indent(
_pipe@8,
3,
<<"}"/utf8>>
),
oaspec@util@string_extra:indent(_pipe@9, 1, <<"}"/utf8>>);
{{some, Min@1}, none} ->
_pipe@10 = Sb@2,
_pipe@11 = oaspec@util@string_extra:indent(
_pipe@10,
1,
<<<<"case value < "/utf8,
(erlang:integer_to_binary(Min@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@12 = oaspec@util@string_extra:indent(
_pipe@11,
2,
<<<<"True -> Error(\"must be at least "/utf8,
(erlang:integer_to_binary(Min@1))/binary>>/binary,
"\")"/utf8>>
),
_pipe@13 = oaspec@util@string_extra:indent(
_pipe@12,
2,
<<"False -> Ok(value)"/utf8>>
),
oaspec@util@string_extra:indent(_pipe@13, 1, <<"}"/utf8>>);
{none, {some, Max@1}} ->
_pipe@14 = Sb@2,
_pipe@15 = oaspec@util@string_extra:indent(
_pipe@14,
1,
<<<<"case value > "/utf8,
(erlang:integer_to_binary(Max@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@16 = oaspec@util@string_extra:indent(
_pipe@15,
2,
<<<<"True -> Error(\"must be at most "/utf8,
(erlang:integer_to_binary(Max@1))/binary>>/binary,
"\")"/utf8>>
),
_pipe@17 = oaspec@util@string_extra:indent(
_pipe@16,
2,
<<"False -> Ok(value)"/utf8>>
),
oaspec@util@string_extra:indent(_pipe@17, 1, <<"}"/utf8>>);
{none, none} ->
Sb@2
end,
_pipe@18 = Sb@3,
_pipe@19 = oaspec@util@string_extra:line(_pipe@18, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@19)
end.
-file("src/oaspec/codegen/guards.gleam", 525).
?DOC(" Generate a float range validation guard.\n").
-spec generate_float_guard(
gleam@string_tree:string_tree(),
binary(),
binary(),
gleam@option:option(float()),
gleam@option:option(float())
) -> gleam@string_tree:string_tree().
generate_float_guard(Sb, Schema_name, Prop_name, Minimum, Maximum) ->
case {Minimum, Maximum} of
{none, none} ->
Sb;
{_, _} ->
Fn_name = guard_function_name(
Schema_name,
Prop_name,
<<"range"/utf8>>
),
Sb@1 = begin
_pipe = Sb,
oaspec@util@string_extra:line(
_pipe,
<<<<<<"/// Validate float range for "/utf8,
Schema_name/binary>>/binary,
(field_label(Prop_name))/binary>>/binary,
"."/utf8>>
)
end,
Sb@2 = begin
_pipe@1 = Sb@1,
oaspec@util@string_extra:line(
_pipe@1,
<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: Float) -> Result(Float, String) {"/utf8>>
)
end,
Sb@3 = case {Minimum, Maximum} of
{{some, Min}, {some, Max}} ->
_pipe@2 = Sb@2,
_pipe@3 = oaspec@util@string_extra:indent(
_pipe@2,
1,
<<<<"case value <. "/utf8,
(gleam_stdlib:float_to_string(Min))/binary>>/binary,
" {"/utf8>>
),
_pipe@4 = oaspec@util@string_extra:indent(
_pipe@3,
2,
<<<<"True -> Error(\"must be at least "/utf8,
(gleam_stdlib:float_to_string(Min))/binary>>/binary,
"\")"/utf8>>
),
_pipe@5 = oaspec@util@string_extra:indent(
_pipe@4,
2,
<<"False ->"/utf8>>
),
_pipe@6 = oaspec@util@string_extra:indent(
_pipe@5,
3,
<<<<"case value >. "/utf8,
(gleam_stdlib:float_to_string(Max))/binary>>/binary,
" {"/utf8>>
),
_pipe@7 = oaspec@util@string_extra:indent(
_pipe@6,
4,
<<<<"True -> Error(\"must be at most "/utf8,
(gleam_stdlib:float_to_string(Max))/binary>>/binary,
"\")"/utf8>>
),
_pipe@8 = oaspec@util@string_extra:indent(
_pipe@7,
4,
<<"False -> Ok(value)"/utf8>>
),
_pipe@9 = oaspec@util@string_extra:indent(
_pipe@8,
3,
<<"}"/utf8>>
),
oaspec@util@string_extra:indent(_pipe@9, 1, <<"}"/utf8>>);
{{some, Min@1}, none} ->
_pipe@10 = Sb@2,
_pipe@11 = oaspec@util@string_extra:indent(
_pipe@10,
1,
<<<<"case value <. "/utf8,
(gleam_stdlib:float_to_string(Min@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@12 = oaspec@util@string_extra:indent(
_pipe@11,
2,
<<<<"True -> Error(\"must be at least "/utf8,
(gleam_stdlib:float_to_string(Min@1))/binary>>/binary,
"\")"/utf8>>
),
_pipe@13 = oaspec@util@string_extra:indent(
_pipe@12,
2,
<<"False -> Ok(value)"/utf8>>
),
oaspec@util@string_extra:indent(_pipe@13, 1, <<"}"/utf8>>);
{none, {some, Max@1}} ->
_pipe@14 = Sb@2,
_pipe@15 = oaspec@util@string_extra:indent(
_pipe@14,
1,
<<<<"case value >. "/utf8,
(gleam_stdlib:float_to_string(Max@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@16 = oaspec@util@string_extra:indent(
_pipe@15,
2,
<<<<"True -> Error(\"must be at most "/utf8,
(gleam_stdlib:float_to_string(Max@1))/binary>>/binary,
"\")"/utf8>>
),
_pipe@17 = oaspec@util@string_extra:indent(
_pipe@16,
2,
<<"False -> Ok(value)"/utf8>>
),
oaspec@util@string_extra:indent(_pipe@17, 1, <<"}"/utf8>>);
{none, none} ->
Sb@2
end,
_pipe@18 = Sb@3,
_pipe@19 = oaspec@util@string_extra:line(_pipe@18, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@19)
end.
-file("src/oaspec/codegen/guards.gleam", 594).
?DOC(" Generate an integer exclusive range validation guard.\n").
-spec generate_integer_exclusive_guard(
gleam@string_tree:string_tree(),
binary(),
binary(),
gleam@option:option(integer()),
gleam@option:option(integer())
) -> gleam@string_tree:string_tree().
generate_integer_exclusive_guard(
Sb,
Schema_name,
Prop_name,
Exclusive_minimum,
Exclusive_maximum
) ->
case {Exclusive_minimum, Exclusive_maximum} of
{none, none} ->
Sb;
{_, _} ->
Fn_name = guard_function_name(
Schema_name,
Prop_name,
<<"exclusive_range"/utf8>>
),
Sb@1 = begin
_pipe = Sb,
oaspec@util@string_extra:line(
_pipe,
<<<<<<"/// Validate integer exclusive range for "/utf8,
Schema_name/binary>>/binary,
(field_label(Prop_name))/binary>>/binary,
"."/utf8>>
)
end,
Sb@2 = begin
_pipe@1 = Sb@1,
oaspec@util@string_extra:line(
_pipe@1,
<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: Int) -> Result(Int, String) {"/utf8>>
)
end,
Sb@3 = case {Exclusive_minimum, Exclusive_maximum} of
{{some, Min}, {some, Max}} ->
_pipe@2 = Sb@2,
_pipe@3 = oaspec@util@string_extra:indent(
_pipe@2,
1,
<<<<"case value > "/utf8,
(erlang:integer_to_binary(Min))/binary>>/binary,
" {"/utf8>>
),
_pipe@4 = oaspec@util@string_extra:indent(
_pipe@3,
2,
<<<<"False -> Error(\"must be greater than "/utf8,
(erlang:integer_to_binary(Min))/binary>>/binary,
"\")"/utf8>>
),
_pipe@5 = oaspec@util@string_extra:indent(
_pipe@4,
2,
<<"True ->"/utf8>>
),
_pipe@6 = oaspec@util@string_extra:indent(
_pipe@5,
3,
<<<<"case value < "/utf8,
(erlang:integer_to_binary(Max))/binary>>/binary,
" {"/utf8>>
),
_pipe@7 = oaspec@util@string_extra:indent(
_pipe@6,
4,
<<<<"False -> Error(\"must be less than "/utf8,
(erlang:integer_to_binary(Max))/binary>>/binary,
"\")"/utf8>>
),
_pipe@8 = oaspec@util@string_extra:indent(
_pipe@7,
4,
<<"True -> Ok(value)"/utf8>>
),
_pipe@9 = oaspec@util@string_extra:indent(
_pipe@8,
3,
<<"}"/utf8>>
),
oaspec@util@string_extra:indent(_pipe@9, 1, <<"}"/utf8>>);
{{some, Min@1}, none} ->
_pipe@10 = Sb@2,
_pipe@11 = oaspec@util@string_extra:indent(
_pipe@10,
1,
<<<<"case value > "/utf8,
(erlang:integer_to_binary(Min@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@12 = oaspec@util@string_extra:indent(
_pipe@11,
2,
<<<<"False -> Error(\"must be greater than "/utf8,
(erlang:integer_to_binary(Min@1))/binary>>/binary,
"\")"/utf8>>
),
_pipe@13 = oaspec@util@string_extra:indent(
_pipe@12,
2,
<<"True -> Ok(value)"/utf8>>
),
oaspec@util@string_extra:indent(_pipe@13, 1, <<"}"/utf8>>);
{none, {some, Max@1}} ->
_pipe@14 = Sb@2,
_pipe@15 = oaspec@util@string_extra:indent(
_pipe@14,
1,
<<<<"case value < "/utf8,
(erlang:integer_to_binary(Max@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@16 = oaspec@util@string_extra:indent(
_pipe@15,
2,
<<<<"False -> Error(\"must be less than "/utf8,
(erlang:integer_to_binary(Max@1))/binary>>/binary,
"\")"/utf8>>
),
_pipe@17 = oaspec@util@string_extra:indent(
_pipe@16,
2,
<<"True -> Ok(value)"/utf8>>
),
oaspec@util@string_extra:indent(_pipe@17, 1, <<"}"/utf8>>);
{none, none} ->
Sb@2
end,
_pipe@18 = Sb@3,
_pipe@19 = oaspec@util@string_extra:line(_pipe@18, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@19)
end.
-file("src/oaspec/codegen/guards.gleam", 668).
?DOC(" Generate an integer multipleOf validation guard.\n").
-spec generate_integer_multiple_of_guard(
gleam@string_tree:string_tree(),
binary(),
binary(),
gleam@option:option(integer())
) -> gleam@string_tree:string_tree().
generate_integer_multiple_of_guard(Sb, Schema_name, Prop_name, Multiple_of) ->
case Multiple_of of
none ->
Sb;
{some, M} ->
Fn_name = guard_function_name(
Schema_name,
Prop_name,
<<"multiple_of"/utf8>>
),
_pipe = Sb,
_pipe@1 = oaspec@util@string_extra:line(
_pipe,
<<<<<<"/// Validate integer multipleOf for "/utf8,
Schema_name/binary>>/binary,
(field_label(Prop_name))/binary>>/binary,
"."/utf8>>
),
_pipe@2 = oaspec@util@string_extra:line(
_pipe@1,
<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: Int) -> Result(Int, String) {"/utf8>>
),
_pipe@3 = oaspec@util@string_extra:indent(
_pipe@2,
1,
<<<<"case value % "/utf8, (erlang:integer_to_binary(M))/binary>>/binary,
" == 0 {"/utf8>>
),
_pipe@4 = oaspec@util@string_extra:indent(
_pipe@3,
2,
<<<<"False -> Error(\"must be a multiple of "/utf8,
(erlang:integer_to_binary(M))/binary>>/binary,
"\")"/utf8>>
),
_pipe@5 = oaspec@util@string_extra:indent(
_pipe@4,
2,
<<"True -> Ok(value)"/utf8>>
),
_pipe@6 = oaspec@util@string_extra:indent(_pipe@5, 1, <<"}"/utf8>>),
_pipe@7 = oaspec@util@string_extra:line(_pipe@6, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@7)
end.
-file("src/oaspec/codegen/guards.gleam", 702).
?DOC(" Generate a float exclusive range validation guard.\n").
-spec generate_float_exclusive_guard(
gleam@string_tree:string_tree(),
binary(),
binary(),
gleam@option:option(float()),
gleam@option:option(float())
) -> gleam@string_tree:string_tree().
generate_float_exclusive_guard(
Sb,
Schema_name,
Prop_name,
Exclusive_minimum,
Exclusive_maximum
) ->
case {Exclusive_minimum, Exclusive_maximum} of
{none, none} ->
Sb;
{_, _} ->
Fn_name = guard_function_name(
Schema_name,
Prop_name,
<<"exclusive_range"/utf8>>
),
Sb@1 = begin
_pipe = Sb,
oaspec@util@string_extra:line(
_pipe,
<<<<<<"/// Validate float exclusive range for "/utf8,
Schema_name/binary>>/binary,
(field_label(Prop_name))/binary>>/binary,
"."/utf8>>
)
end,
Sb@2 = begin
_pipe@1 = Sb@1,
oaspec@util@string_extra:line(
_pipe@1,
<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: Float) -> Result(Float, String) {"/utf8>>
)
end,
Sb@3 = case {Exclusive_minimum, Exclusive_maximum} of
{{some, Min}, {some, Max}} ->
_pipe@2 = Sb@2,
_pipe@3 = oaspec@util@string_extra:indent(
_pipe@2,
1,
<<<<"case value >. "/utf8,
(gleam_stdlib:float_to_string(Min))/binary>>/binary,
" {"/utf8>>
),
_pipe@4 = oaspec@util@string_extra:indent(
_pipe@3,
2,
<<<<"False -> Error(\"must be greater than "/utf8,
(gleam_stdlib:float_to_string(Min))/binary>>/binary,
"\")"/utf8>>
),
_pipe@5 = oaspec@util@string_extra:indent(
_pipe@4,
2,
<<"True ->"/utf8>>
),
_pipe@6 = oaspec@util@string_extra:indent(
_pipe@5,
3,
<<<<"case value <. "/utf8,
(gleam_stdlib:float_to_string(Max))/binary>>/binary,
" {"/utf8>>
),
_pipe@7 = oaspec@util@string_extra:indent(
_pipe@6,
4,
<<<<"False -> Error(\"must be less than "/utf8,
(gleam_stdlib:float_to_string(Max))/binary>>/binary,
"\")"/utf8>>
),
_pipe@8 = oaspec@util@string_extra:indent(
_pipe@7,
4,
<<"True -> Ok(value)"/utf8>>
),
_pipe@9 = oaspec@util@string_extra:indent(
_pipe@8,
3,
<<"}"/utf8>>
),
oaspec@util@string_extra:indent(_pipe@9, 1, <<"}"/utf8>>);
{{some, Min@1}, none} ->
_pipe@10 = Sb@2,
_pipe@11 = oaspec@util@string_extra:indent(
_pipe@10,
1,
<<<<"case value >. "/utf8,
(gleam_stdlib:float_to_string(Min@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@12 = oaspec@util@string_extra:indent(
_pipe@11,
2,
<<<<"False -> Error(\"must be greater than "/utf8,
(gleam_stdlib:float_to_string(Min@1))/binary>>/binary,
"\")"/utf8>>
),
_pipe@13 = oaspec@util@string_extra:indent(
_pipe@12,
2,
<<"True -> Ok(value)"/utf8>>
),
oaspec@util@string_extra:indent(_pipe@13, 1, <<"}"/utf8>>);
{none, {some, Max@1}} ->
_pipe@14 = Sb@2,
_pipe@15 = oaspec@util@string_extra:indent(
_pipe@14,
1,
<<<<"case value <. "/utf8,
(gleam_stdlib:float_to_string(Max@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@16 = oaspec@util@string_extra:indent(
_pipe@15,
2,
<<<<"False -> Error(\"must be less than "/utf8,
(gleam_stdlib:float_to_string(Max@1))/binary>>/binary,
"\")"/utf8>>
),
_pipe@17 = oaspec@util@string_extra:indent(
_pipe@16,
2,
<<"True -> Ok(value)"/utf8>>
),
oaspec@util@string_extra:indent(_pipe@17, 1, <<"}"/utf8>>);
{none, none} ->
Sb@2
end,
_pipe@18 = Sb@3,
_pipe@19 = oaspec@util@string_extra:line(_pipe@18, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@19)
end.
-file("src/oaspec/codegen/guards.gleam", 780).
?DOC(" Generate a float multipleOf validation guard.\n").
-spec generate_float_multiple_of_guard(
gleam@string_tree:string_tree(),
binary(),
binary(),
gleam@option:option(float())
) -> gleam@string_tree:string_tree().
generate_float_multiple_of_guard(Sb, Schema_name, Prop_name, Multiple_of) ->
case Multiple_of of
none ->
Sb;
{some, M} ->
Fn_name = guard_function_name(
Schema_name,
Prop_name,
<<"multiple_of"/utf8>>
),
_pipe = Sb,
_pipe@1 = oaspec@util@string_extra:line(
_pipe,
<<<<<<"/// Validate float multipleOf for "/utf8,
Schema_name/binary>>/binary,
(field_label(Prop_name))/binary>>/binary,
"."/utf8>>
),
_pipe@2 = oaspec@util@string_extra:line(
_pipe@1,
<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: Float) -> Result(Float, String) {"/utf8>>
),
_pipe@3 = oaspec@util@string_extra:indent(
_pipe@2,
1,
<<<<<<"let remainder = value -. float.truncate(value /. "/utf8,
(gleam_stdlib:float_to_string(M))/binary>>/binary,
" |> int.to_float) *. "/utf8>>/binary,
(gleam_stdlib:float_to_string(M))/binary>>
),
_pipe@4 = oaspec@util@string_extra:indent(
_pipe@3,
1,
<<"case remainder == 0.0 || remainder == -0.0 {"/utf8>>
),
_pipe@5 = oaspec@util@string_extra:indent(
_pipe@4,
2,
<<<<"False -> Error(\"must be a multiple of "/utf8,
(gleam_stdlib:float_to_string(M))/binary>>/binary,
"\")"/utf8>>
),
_pipe@6 = oaspec@util@string_extra:indent(
_pipe@5,
2,
<<"True -> Ok(value)"/utf8>>
),
_pipe@7 = oaspec@util@string_extra:indent(_pipe@6, 1, <<"}"/utf8>>),
_pipe@8 = oaspec@util@string_extra:line(_pipe@7, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@8)
end.
-file("src/oaspec/codegen/guards.gleam", 821).
?DOC(" Generate a list length validation guard.\n").
-spec generate_list_guard(
gleam@string_tree:string_tree(),
binary(),
binary(),
gleam@option:option(integer()),
gleam@option:option(integer())
) -> gleam@string_tree:string_tree().
generate_list_guard(Sb, Schema_name, Prop_name, Min_items, Max_items) ->
case {Min_items, Max_items} of
{none, none} ->
Sb;
{_, _} ->
Fn_name = guard_function_name(
Schema_name,
Prop_name,
<<"length"/utf8>>
),
Sb@1 = begin
_pipe = Sb,
oaspec@util@string_extra:line(
_pipe,
<<<<<<"/// Validate list length for "/utf8,
Schema_name/binary>>/binary,
(field_label(Prop_name))/binary>>/binary,
"."/utf8>>
)
end,
Sb@2 = begin
_pipe@1 = Sb@1,
oaspec@util@string_extra:line(
_pipe@1,
<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: List(a)) -> Result(List(a), String) {"/utf8>>
)
end,
Sb@3 = begin
_pipe@2 = Sb@2,
oaspec@util@string_extra:indent(
_pipe@2,
1,
<<"let len = list.length(value)"/utf8>>
)
end,
Sb@4 = case {Min_items, Max_items} of
{{some, Min}, {some, Max}} ->
_pipe@3 = Sb@3,
_pipe@4 = oaspec@util@string_extra:indent(
_pipe@3,
1,
<<<<"case len < "/utf8,
(erlang:integer_to_binary(Min))/binary>>/binary,
" {"/utf8>>
),
_pipe@5 = oaspec@util@string_extra:indent(
_pipe@4,
2,
<<<<"True -> Error(\"must have at least "/utf8,
(erlang:integer_to_binary(Min))/binary>>/binary,
" items\")"/utf8>>
),
_pipe@6 = oaspec@util@string_extra:indent(
_pipe@5,
2,
<<"False ->"/utf8>>
),
_pipe@7 = oaspec@util@string_extra:indent(
_pipe@6,
3,
<<<<"case len > "/utf8,
(erlang:integer_to_binary(Max))/binary>>/binary,
" {"/utf8>>
),
_pipe@8 = oaspec@util@string_extra:indent(
_pipe@7,
4,
<<<<"True -> Error(\"must have at most "/utf8,
(erlang:integer_to_binary(Max))/binary>>/binary,
" items\")"/utf8>>
),
_pipe@9 = oaspec@util@string_extra:indent(
_pipe@8,
4,
<<"False -> Ok(value)"/utf8>>
),
_pipe@10 = oaspec@util@string_extra:indent(
_pipe@9,
3,
<<"}"/utf8>>
),
oaspec@util@string_extra:indent(_pipe@10, 1, <<"}"/utf8>>);
{{some, Min@1}, none} ->
_pipe@11 = Sb@3,
_pipe@12 = oaspec@util@string_extra:indent(
_pipe@11,
1,
<<<<"case len < "/utf8,
(erlang:integer_to_binary(Min@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@13 = oaspec@util@string_extra:indent(
_pipe@12,
2,
<<<<"True -> Error(\"must have at least "/utf8,
(erlang:integer_to_binary(Min@1))/binary>>/binary,
" items\")"/utf8>>
),
_pipe@14 = oaspec@util@string_extra:indent(
_pipe@13,
2,
<<"False -> Ok(value)"/utf8>>
),
oaspec@util@string_extra:indent(_pipe@14, 1, <<"}"/utf8>>);
{none, {some, Max@1}} ->
_pipe@15 = Sb@3,
_pipe@16 = oaspec@util@string_extra:indent(
_pipe@15,
1,
<<<<"case len > "/utf8,
(erlang:integer_to_binary(Max@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@17 = oaspec@util@string_extra:indent(
_pipe@16,
2,
<<<<"True -> Error(\"must have at most "/utf8,
(erlang:integer_to_binary(Max@1))/binary>>/binary,
" items\")"/utf8>>
),
_pipe@18 = oaspec@util@string_extra:indent(
_pipe@17,
2,
<<"False -> Ok(value)"/utf8>>
),
oaspec@util@string_extra:indent(_pipe@18, 1, <<"}"/utf8>>);
{none, none} ->
Sb@3
end,
_pipe@19 = Sb@4,
_pipe@20 = oaspec@util@string_extra:line(_pipe@19, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@20)
end.
-file("src/oaspec/codegen/guards.gleam", 903).
?DOC(" Generate a uniqueItems validation guard.\n").
-spec generate_unique_items_guard(
gleam@string_tree:string_tree(),
binary(),
binary(),
boolean()
) -> gleam@string_tree:string_tree().
generate_unique_items_guard(Sb, Schema_name, Prop_name, Unique_items) ->
case Unique_items of
false ->
Sb;
true ->
Fn_name = guard_function_name(
Schema_name,
Prop_name,
<<"unique"/utf8>>
),
_pipe = Sb,
_pipe@1 = oaspec@util@string_extra:line(
_pipe,
<<<<<<"/// Validate unique items for "/utf8,
Schema_name/binary>>/binary,
(field_label(Prop_name))/binary>>/binary,
"."/utf8>>
),
_pipe@2 = oaspec@util@string_extra:line(
_pipe@1,
<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: List(a)) -> Result(List(a), String) {"/utf8>>
),
_pipe@3 = oaspec@util@string_extra:indent(
_pipe@2,
1,
<<"case list.length(value) == list.length(list.unique(value)) {"/utf8>>
),
_pipe@4 = oaspec@util@string_extra:indent(
_pipe@3,
2,
<<"True -> Ok(value)"/utf8>>
),
_pipe@5 = oaspec@util@string_extra:indent(
_pipe@4,
2,
<<"False -> Error(\"items must be unique\")"/utf8>>
),
_pipe@6 = oaspec@util@string_extra:indent(_pipe@5, 1, <<"}"/utf8>>),
_pipe@7 = oaspec@util@string_extra:line(_pipe@6, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@7)
end.
-file("src/oaspec/codegen/guards.gleam", 309).
?DOC(" Generate a guard for a specific field based on its schema type and constraints.\n").
-spec generate_field_guard(
gleam@string_tree:string_tree(),
binary(),
binary(),
oaspec@openapi@schema:schema_ref(),
oaspec@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_field_guard(Sb, Schema_name, Prop_name, Prop_ref, Ctx) ->
Resolved = case Prop_ref of
{inline, Schema} ->
{ok, Schema};
{reference, _, _} ->
oaspec@openapi@resolver:resolve_schema_ref(
Prop_ref,
erlang:element(2, Ctx)
)
end,
case Resolved of
{ok, {string_schema, _, _, _, Min_length, Max_length, _}} ->
generate_string_guard(
Sb,
Schema_name,
Prop_name,
Min_length,
Max_length
);
{ok,
{integer_schema,
_,
_,
Minimum,
Maximum,
Exclusive_minimum,
Exclusive_maximum,
Multiple_of}} ->
Sb@1 = generate_integer_guard(
Sb,
Schema_name,
Prop_name,
Minimum,
Maximum
),
Sb@2 = generate_integer_exclusive_guard(
Sb@1,
Schema_name,
Prop_name,
Exclusive_minimum,
Exclusive_maximum
),
generate_integer_multiple_of_guard(
Sb@2,
Schema_name,
Prop_name,
Multiple_of
);
{ok,
{number_schema,
_,
_,
Minimum@1,
Maximum@1,
Exclusive_minimum@1,
Exclusive_maximum@1,
Multiple_of@1}} ->
Sb@3 = generate_float_guard(
Sb,
Schema_name,
Prop_name,
Minimum@1,
Maximum@1
),
Sb@4 = generate_float_exclusive_guard(
Sb@3,
Schema_name,
Prop_name,
Exclusive_minimum@1,
Exclusive_maximum@1
),
generate_float_multiple_of_guard(
Sb@4,
Schema_name,
Prop_name,
Multiple_of@1
);
{ok, {array_schema, _, _, Min_items, Max_items, Unique_items}} ->
Sb@5 = generate_list_guard(
Sb,
Schema_name,
Prop_name,
Min_items,
Max_items
),
generate_unique_items_guard(
Sb@5,
Schema_name,
Prop_name,
Unique_items
);
_ ->
Sb
end.
-file("src/oaspec/codegen/guards.gleam", 937).
?DOC(" Generate a minProperties/maxProperties validation guard for objects.\n").
-spec generate_properties_count_guard(
gleam@string_tree:string_tree(),
binary(),
binary(),
gleam@option:option(integer()),
gleam@option:option(integer())
) -> gleam@string_tree:string_tree().
generate_properties_count_guard(
Sb,
Schema_name,
Prop_name,
Min_properties,
Max_properties
) ->
case {Min_properties, Max_properties} of
{none, none} ->
Sb;
{_, _} ->
Fn_name = guard_function_name(
Schema_name,
Prop_name,
<<"properties"/utf8>>
),
Sb@1 = begin
_pipe = Sb,
_pipe@1 = oaspec@util@string_extra:line(
_pipe,
<<<<<<"/// Validate property count for "/utf8,
Schema_name/binary>>/binary,
(field_label(Prop_name))/binary>>/binary,
"."/utf8>>
),
_pipe@2 = oaspec@util@string_extra:line(
_pipe@1,
<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: Dict(k, v)) -> Result(Dict(k, v), String) {"/utf8>>
),
oaspec@util@string_extra:indent(
_pipe@2,
1,
<<"let count = dict.size(value)"/utf8>>
)
end,
Sb@2 = case {Min_properties, Max_properties} of
{{some, Min}, {some, Max}} ->
_pipe@3 = Sb@1,
_pipe@4 = oaspec@util@string_extra:indent(
_pipe@3,
1,
<<<<"case count < "/utf8,
(erlang:integer_to_binary(Min))/binary>>/binary,
" {"/utf8>>
),
_pipe@5 = oaspec@util@string_extra:indent(
_pipe@4,
2,
<<<<"True -> Error(\"must have at least "/utf8,
(erlang:integer_to_binary(Min))/binary>>/binary,
" properties\")"/utf8>>
),
_pipe@6 = oaspec@util@string_extra:indent(
_pipe@5,
2,
<<"False ->"/utf8>>
),
_pipe@7 = oaspec@util@string_extra:indent(
_pipe@6,
3,
<<<<"case count > "/utf8,
(erlang:integer_to_binary(Max))/binary>>/binary,
" {"/utf8>>
),
_pipe@8 = oaspec@util@string_extra:indent(
_pipe@7,
4,
<<<<"True -> Error(\"must have at most "/utf8,
(erlang:integer_to_binary(Max))/binary>>/binary,
" properties\")"/utf8>>
),
_pipe@9 = oaspec@util@string_extra:indent(
_pipe@8,
4,
<<"False -> Ok(value)"/utf8>>
),
_pipe@10 = oaspec@util@string_extra:indent(
_pipe@9,
3,
<<"}"/utf8>>
),
oaspec@util@string_extra:indent(_pipe@10, 1, <<"}"/utf8>>);
{{some, Min@1}, none} ->
_pipe@11 = Sb@1,
_pipe@12 = oaspec@util@string_extra:indent(
_pipe@11,
1,
<<<<"case count < "/utf8,
(erlang:integer_to_binary(Min@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@13 = oaspec@util@string_extra:indent(
_pipe@12,
2,
<<<<"True -> Error(\"must have at least "/utf8,
(erlang:integer_to_binary(Min@1))/binary>>/binary,
" properties\")"/utf8>>
),
_pipe@14 = oaspec@util@string_extra:indent(
_pipe@13,
2,
<<"False -> Ok(value)"/utf8>>
),
oaspec@util@string_extra:indent(_pipe@14, 1, <<"}"/utf8>>);
{none, {some, Max@1}} ->
_pipe@15 = Sb@1,
_pipe@16 = oaspec@util@string_extra:indent(
_pipe@15,
1,
<<<<"case count > "/utf8,
(erlang:integer_to_binary(Max@1))/binary>>/binary,
" {"/utf8>>
),
_pipe@17 = oaspec@util@string_extra:indent(
_pipe@16,
2,
<<<<"True -> Error(\"must have at most "/utf8,
(erlang:integer_to_binary(Max@1))/binary>>/binary,
" properties\")"/utf8>>
),
_pipe@18 = oaspec@util@string_extra:indent(
_pipe@17,
2,
<<"False -> Ok(value)"/utf8>>
),
oaspec@util@string_extra:indent(_pipe@18, 1, <<"}"/utf8>>);
{none, none} ->
Sb@1
end,
_pipe@19 = Sb@2,
_pipe@20 = oaspec@util@string_extra:line(_pipe@19, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@20)
end.
-file("src/oaspec/codegen/guards.gleam", 218).
?DOC(" Generate guard functions for fields within a schema object.\n").
-spec generate_guards_for_schema_object(
gleam@string_tree:string_tree(),
binary(),
oaspec@openapi@schema:schema_object(),
oaspec@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_guards_for_schema_object(Sb, Name, Schema, Ctx) ->
case Schema of
{object_schema, _, Properties, _, _, _, Min_properties, Max_properties} ->
Sb@1 = generate_properties_count_guard(
Sb,
Name,
<<""/utf8>>,
Min_properties,
Max_properties
),
Props = maps:to_list(Properties),
gleam@list:fold(
Props,
Sb@1,
fun(Sb@2, Entry) ->
{Prop_name, Prop_ref} = Entry,
generate_field_guard(Sb@2, Name, Prop_name, Prop_ref, Ctx)
end
);
{all_of_schema, _, Schemas} ->
Merged_props = gleam@list:fold(
Schemas,
maps:new(),
fun(Acc, S_ref) -> case S_ref of
{inline,
{object_schema, _, Properties@1, _, _, _, _, _}} ->
maps:merge(Acc, Properties@1);
{reference, _, _} ->
case oaspec@openapi@resolver:resolve_schema_ref(
S_ref,
erlang:element(2, Ctx)
) of
{ok,
{object_schema,
_,
Properties@2,
_,
_,
_,
_,
_}} ->
maps:merge(Acc, Properties@2);
_ ->
Acc
end;
_ ->
Acc
end end
),
Props@1 = maps:to_list(Merged_props),
gleam@list:fold(
Props@1,
Sb,
fun(Sb@3, Entry@1) ->
{Prop_name@1, Prop_ref@1} = Entry@1,
generate_field_guard(
Sb@3,
Name,
Prop_name@1,
Prop_ref@1,
Ctx
)
end
);
{string_schema, _, _, _, Min_length, Max_length, _} ->
generate_string_guard(Sb, Name, <<""/utf8>>, Min_length, Max_length);
{integer_schema,
_,
_,
Minimum,
Maximum,
Exclusive_minimum,
Exclusive_maximum,
Multiple_of} ->
Sb@4 = generate_integer_guard(
Sb,
Name,
<<""/utf8>>,
Minimum,
Maximum
),
Sb@5 = generate_integer_exclusive_guard(
Sb@4,
Name,
<<""/utf8>>,
Exclusive_minimum,
Exclusive_maximum
),
generate_integer_multiple_of_guard(
Sb@5,
Name,
<<""/utf8>>,
Multiple_of
);
{number_schema,
_,
_,
Minimum@1,
Maximum@1,
Exclusive_minimum@1,
Exclusive_maximum@1,
Multiple_of@1} ->
Sb@6 = generate_float_guard(
Sb,
Name,
<<""/utf8>>,
Minimum@1,
Maximum@1
),
Sb@7 = generate_float_exclusive_guard(
Sb@6,
Name,
<<""/utf8>>,
Exclusive_minimum@1,
Exclusive_maximum@1
),
generate_float_multiple_of_guard(
Sb@7,
Name,
<<""/utf8>>,
Multiple_of@1
);
{array_schema, _, _, Min_items, Max_items, Unique_items} ->
Sb@8 = generate_list_guard(
Sb,
Name,
<<""/utf8>>,
Min_items,
Max_items
),
generate_unique_items_guard(Sb@8, Name, <<""/utf8>>, Unique_items);
_ ->
Sb
end.
-file("src/oaspec/codegen/guards.gleam", 198).
?DOC(" Generate guard functions for a single schema's constrained fields.\n").
-spec generate_guards_for_schema(
gleam@string_tree:string_tree(),
binary(),
oaspec@openapi@schema:schema_ref(),
oaspec@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_guards_for_schema(Sb, Name, Schema_ref, Ctx) ->
case Schema_ref of
{inline, Schema} ->
generate_guards_for_schema_object(Sb, Name, Schema, Ctx);
{reference, _, Name@1} ->
Resolved_name = Name@1,
case oaspec@openapi@resolver:resolve_schema_ref(
Schema_ref,
erlang:element(2, Ctx)
) of
{ok, Schema@1} ->
generate_guards_for_schema_object(
Sb,
Resolved_name,
Schema@1,
Ctx
);
_ ->
Sb
end
end.
-file("src/oaspec/codegen/guards.gleam", 1109).
?DOC(" Determine the Gleam type for the composite validator parameter.\n").
-spec composite_validator_type(
binary(),
oaspec@openapi@schema:schema_ref(),
oaspec@codegen@context:context()
) -> binary().
composite_validator_type(Name, Schema_ref, Ctx) ->
Schema = case Schema_ref of
{inline, S} ->
{ok, S};
{reference, _, _} ->
oaspec@openapi@resolver:resolve_schema_ref(
Schema_ref,
erlang:element(2, Ctx)
)
end,
case Schema of
{ok, {object_schema, _, _, _, _, _, _, _}} ->
<<"types."/utf8,
(oaspec@util@naming:schema_to_type_name(Name))/binary>>;
{ok, {all_of_schema, _, _}} ->
<<"types."/utf8,
(oaspec@util@naming:schema_to_type_name(Name))/binary>>;
{ok, S@1} ->
oaspec@codegen@types:schema_to_gleam_type(S@1, Ctx);
_ ->
<<"types."/utf8,
(oaspec@util@naming:schema_to_type_name(Name))/binary>>
end.
-file("src/oaspec/codegen/guards.gleam", 1260).
?DOC(" Collect guard calls for a single field.\n").
-spec collect_field_guard_calls(
binary(),
binary(),
oaspec@openapi@schema:schema_ref(),
boolean(),
oaspec@codegen@context:context()
) -> list({binary(), binary(), boolean()}).
collect_field_guard_calls(Schema_name, Prop_name, Prop_ref, Is_required, Ctx) ->
Resolved = case Prop_ref of
{inline, Schema} ->
{ok, Schema};
{reference, _, _} ->
oaspec@openapi@resolver:resolve_schema_ref(
Prop_ref,
erlang:element(2, Ctx)
)
end,
Accessor = <<"value."/utf8,
(oaspec@util@naming:to_snake_case(Prop_name))/binary>>,
case Resolved of
{ok, {string_schema, _, _, _, Min_length, Max_length, _}} ->
case {Min_length, Max_length} of
{none, none} ->
[];
{_, _} ->
[{guard_function_name(
Schema_name,
Prop_name,
<<"length"/utf8>>
),
Accessor,
Is_required}]
end;
{ok,
{integer_schema,
_,
_,
Minimum,
Maximum,
Exclusive_minimum,
Exclusive_maximum,
Multiple_of}} ->
Calls = case {Minimum, Maximum} of
{none, none} ->
[];
{_, _} ->
[{guard_function_name(
Schema_name,
Prop_name,
<<"range"/utf8>>
),
Accessor,
Is_required}]
end,
Calls@1 = case {Exclusive_minimum, Exclusive_maximum} of
{none, none} ->
Calls;
{_, _} ->
lists:append(
Calls,
[{guard_function_name(
Schema_name,
Prop_name,
<<"exclusive_range"/utf8>>
),
Accessor,
Is_required}]
)
end,
case Multiple_of of
none ->
Calls@1;
{some, _} ->
lists:append(
Calls@1,
[{guard_function_name(
Schema_name,
Prop_name,
<<"multiple_of"/utf8>>
),
Accessor,
Is_required}]
)
end;
{ok,
{number_schema,
_,
_,
Minimum@1,
Maximum@1,
Exclusive_minimum@1,
Exclusive_maximum@1,
Multiple_of@1}} ->
Calls@2 = case {Minimum@1, Maximum@1} of
{none, none} ->
[];
{_, _} ->
[{guard_function_name(
Schema_name,
Prop_name,
<<"range"/utf8>>
),
Accessor,
Is_required}]
end,
Calls@3 = case {Exclusive_minimum@1, Exclusive_maximum@1} of
{none, none} ->
Calls@2;
{_, _} ->
lists:append(
Calls@2,
[{guard_function_name(
Schema_name,
Prop_name,
<<"exclusive_range"/utf8>>
),
Accessor,
Is_required}]
)
end,
case Multiple_of@1 of
none ->
Calls@3;
{some, _} ->
lists:append(
Calls@3,
[{guard_function_name(
Schema_name,
Prop_name,
<<"multiple_of"/utf8>>
),
Accessor,
Is_required}]
)
end;
{ok, {array_schema, _, _, Min_items, Max_items, Unique_items}} ->
Length_calls = case {Min_items, Max_items} of
{none, none} ->
[];
{_, _} ->
[{guard_function_name(
Schema_name,
Prop_name,
<<"length"/utf8>>
),
Accessor,
Is_required}]
end,
Unique_calls = case Unique_items of
true ->
[{guard_function_name(
Schema_name,
Prop_name,
<<"unique"/utf8>>
),
Accessor,
Is_required}];
false ->
[]
end,
lists:append(Length_calls, Unique_calls);
_ ->
[]
end.
-file("src/oaspec/codegen/guards.gleam", 1398).
-spec merge_allof_props_and_required(
list(oaspec@openapi@schema:schema_ref()),
oaspec@codegen@context:context()
) -> merged_props().
merge_allof_props_and_required(Schemas, Ctx) ->
gleam@list:fold(
Schemas,
{merged_props, maps:new(), []},
fun(Acc, S_ref) -> case S_ref of
{inline, {object_schema, _, Properties, Required, _, _, _, _}} ->
{merged_props,
maps:merge(erlang:element(2, Acc), Properties),
lists:append(erlang:element(3, Acc), Required)};
{reference, _, _} ->
case oaspec@openapi@resolver:resolve_schema_ref(
S_ref,
erlang:element(2, Ctx)
) of
{ok,
{object_schema,
_,
Properties@1,
Required@1,
_,
_,
_,
_}} ->
{merged_props,
maps:merge(erlang:element(2, Acc), Properties@1),
lists:append(erlang:element(3, Acc), Required@1)};
_ ->
Acc
end;
_ ->
Acc
end end
).
-file("src/oaspec/codegen/guards.gleam", 1134).
?DOC(" Collect all guard function calls for a schema's constrained fields.\n").
-spec collect_guard_calls(
binary(),
oaspec@openapi@schema:schema_ref(),
oaspec@codegen@context:context()
) -> list({binary(), binary(), boolean()}).
collect_guard_calls(Name, Schema_ref, Ctx) ->
Schema = case Schema_ref of
{inline, S} ->
{ok, S};
{reference, _, _} ->
oaspec@openapi@resolver:resolve_schema_ref(
Schema_ref,
erlang:element(2, Ctx)
)
end,
case Schema of
{ok,
{object_schema,
_,
Properties,
Required,
_,
_,
Min_properties,
Max_properties}} ->
Prop_calls = begin
_pipe = maps:to_list(Properties),
gleam@list:flat_map(
_pipe,
fun(Entry) ->
{Prop_name, Prop_ref} = Entry,
Is_required = gleam@list:contains(Required, Prop_name),
collect_field_guard_calls(
Name,
Prop_name,
Prop_ref,
Is_required,
Ctx
)
end
)
end,
Size_calls = case {Min_properties, Max_properties} of
{none, none} ->
[];
{_, _} ->
[{guard_function_name(
Name,
<<""/utf8>>,
<<"properties"/utf8>>
),
<<"value"/utf8>>,
true}]
end,
lists:append(Prop_calls, Size_calls);
{ok, {all_of_schema, _, Schemas}} ->
Merged = merge_allof_props_and_required(Schemas, Ctx),
_pipe@1 = maps:to_list(erlang:element(2, Merged)),
gleam@list:flat_map(
_pipe@1,
fun(Entry@1) ->
{Prop_name@1, Prop_ref@1} = Entry@1,
Is_required@1 = gleam@list:contains(
erlang:element(3, Merged),
Prop_name@1
),
collect_field_guard_calls(
Name,
Prop_name@1,
Prop_ref@1,
Is_required@1,
Ctx
)
end
);
{ok, {string_schema, _, _, _, Min_length, Max_length, _}} ->
case {Min_length, Max_length} of
{none, none} ->
[];
{_, _} ->
[{guard_function_name(Name, <<""/utf8>>, <<"length"/utf8>>),
<<"value"/utf8>>,
true}]
end;
{ok,
{integer_schema,
_,
_,
Minimum,
Maximum,
Exclusive_minimum,
Exclusive_maximum,
Multiple_of}} ->
Calls = case {Minimum, Maximum} of
{none, none} ->
[];
{_, _} ->
[{guard_function_name(Name, <<""/utf8>>, <<"range"/utf8>>),
<<"value"/utf8>>,
true}]
end,
Calls@1 = case {Exclusive_minimum, Exclusive_maximum} of
{none, none} ->
Calls;
{_, _} ->
lists:append(
Calls,
[{guard_function_name(
Name,
<<""/utf8>>,
<<"exclusive_range"/utf8>>
),
<<"value"/utf8>>,
true}]
)
end,
case Multiple_of of
none ->
Calls@1;
{some, _} ->
lists:append(
Calls@1,
[{guard_function_name(
Name,
<<""/utf8>>,
<<"multiple_of"/utf8>>
),
<<"value"/utf8>>,
true}]
)
end;
{ok,
{number_schema,
_,
_,
Minimum@1,
Maximum@1,
Exclusive_minimum@1,
Exclusive_maximum@1,
Multiple_of@1}} ->
Calls@2 = case {Minimum@1, Maximum@1} of
{none, none} ->
[];
{_, _} ->
[{guard_function_name(Name, <<""/utf8>>, <<"range"/utf8>>),
<<"value"/utf8>>,
true}]
end,
Calls@3 = case {Exclusive_minimum@1, Exclusive_maximum@1} of
{none, none} ->
Calls@2;
{_, _} ->
lists:append(
Calls@2,
[{guard_function_name(
Name,
<<""/utf8>>,
<<"exclusive_range"/utf8>>
),
<<"value"/utf8>>,
true}]
)
end,
case Multiple_of@1 of
none ->
Calls@3;
{some, _} ->
lists:append(
Calls@3,
[{guard_function_name(
Name,
<<""/utf8>>,
<<"multiple_of"/utf8>>
),
<<"value"/utf8>>,
true}]
)
end;
{ok, {array_schema, _, _, Min_items, Max_items, Unique_items}} ->
Length_calls = case {Min_items, Max_items} of
{none, none} ->
[];
{_, _} ->
[{guard_function_name(Name, <<""/utf8>>, <<"length"/utf8>>),
<<"value"/utf8>>,
true}]
end,
Unique_calls = case Unique_items of
true ->
[{guard_function_name(Name, <<""/utf8>>, <<"unique"/utf8>>),
<<"value"/utf8>>,
true}];
false ->
[]
end,
lists:append(Length_calls, Unique_calls);
_ ->
[]
end.
-file("src/oaspec/codegen/guards.gleam", 1044).
?DOC(
" Generate a composite validate function for a schema that calls all\n"
" individual field validators. This enables auto-validation by calling\n"
" a single function rather than individual field guards.\n"
).
-spec generate_composite_validator(
gleam@string_tree:string_tree(),
binary(),
oaspec@openapi@schema:schema_ref(),
oaspec@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_composite_validator(Sb, Name, Schema_ref, Ctx) ->
Guard_calls = collect_guard_calls(Name, Schema_ref, Ctx),
case gleam@list:is_empty(Guard_calls) of
true ->
Sb;
false ->
Fn_name = <<"validate_"/utf8,
(oaspec@util@naming:to_snake_case(Name))/binary>>,
Type_name = oaspec@util@naming:schema_to_type_name(Name),
Gleam_type = composite_validator_type(Name, Schema_ref, Ctx),
Sb@1 = begin
_pipe = Sb,
_pipe@1 = oaspec@util@string_extra:doc_comment(
_pipe,
<<<<"Validate all constraints for "/utf8, Type_name/binary>>/binary,
"."/utf8>>
),
_pipe@2 = oaspec@util@string_extra:doc_comment(
_pipe@1,
<<"Auto-calls all field validators and collects errors."/utf8>>
),
_pipe@3 = oaspec@util@string_extra:line(
_pipe@2,
<<<<<<<<<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: "/utf8>>/binary,
Gleam_type/binary>>/binary,
") -> Result("/utf8>>/binary,
Gleam_type/binary>>/binary,
", List(String)) {"/utf8>>
),
oaspec@util@string_extra:indent(
_pipe@3,
1,
<<"let errors = []"/utf8>>
)
end,
Sb@3 = gleam@list:fold(
Guard_calls,
Sb@1,
fun(Sb@2, Call) ->
{Guard_fn, Accessor, Is_required} = Call,
case Is_required of
true ->
_pipe@4 = Sb@2,
_pipe@5 = oaspec@util@string_extra:indent(
_pipe@4,
1,
<<<<<<<<"let errors = case "/utf8,
Guard_fn/binary>>/binary,
"("/utf8>>/binary,
Accessor/binary>>/binary,
") {"/utf8>>
),
_pipe@6 = oaspec@util@string_extra:indent(
_pipe@5,
2,
<<"Ok(_) -> errors"/utf8>>
),
_pipe@7 = oaspec@util@string_extra:indent(
_pipe@6,
2,
<<"Error(msg) -> [msg, ..errors]"/utf8>>
),
oaspec@util@string_extra:indent(
_pipe@7,
1,
<<"}"/utf8>>
);
false ->
_pipe@8 = Sb@2,
_pipe@9 = oaspec@util@string_extra:indent(
_pipe@8,
1,
<<<<"let errors = case "/utf8, Accessor/binary>>/binary,
" {"/utf8>>
),
_pipe@10 = oaspec@util@string_extra:indent(
_pipe@9,
2,
<<<<"option.Some(v) -> case "/utf8,
Guard_fn/binary>>/binary,
"(v) {"/utf8>>
),
_pipe@11 = oaspec@util@string_extra:indent(
_pipe@10,
3,
<<"Ok(_) -> errors"/utf8>>
),
_pipe@12 = oaspec@util@string_extra:indent(
_pipe@11,
3,
<<"Error(msg) -> [msg, ..errors]"/utf8>>
),
_pipe@13 = oaspec@util@string_extra:indent(
_pipe@12,
2,
<<"}"/utf8>>
),
_pipe@14 = oaspec@util@string_extra:indent(
_pipe@13,
2,
<<"option.None -> errors"/utf8>>
),
oaspec@util@string_extra:indent(
_pipe@14,
1,
<<"}"/utf8>>
)
end
end
),
_pipe@15 = Sb@3,
_pipe@16 = oaspec@util@string_extra:indent(
_pipe@15,
1,
<<"case errors {"/utf8>>
),
_pipe@17 = oaspec@util@string_extra:indent(
_pipe@16,
2,
<<"[] -> Ok(value)"/utf8>>
),
_pipe@18 = oaspec@util@string_extra:indent(
_pipe@17,
2,
<<"_ -> Error(errors)"/utf8>>
),
_pipe@19 = oaspec@util@string_extra:indent(
_pipe@18,
1,
<<"}"/utf8>>
),
_pipe@20 = oaspec@util@string_extra:line(_pipe@19, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@20)
end.
-file("src/oaspec/codegen/guards.gleam", 33).
?DOC(" Generate validation guard functions for schemas with constraints.\n").
-spec generate_guards(oaspec@codegen@context:context()) -> binary().
generate_guards(Ctx) ->
Schemas = case erlang:element(5, erlang:element(2, Ctx)) of
{some, Components} ->
gleam@list:sort(
maps:to_list(erlang:element(2, Components)),
fun(A, B) ->
gleam@string:compare(
erlang:element(1, A),
erlang:element(1, B)
)
end
);
none ->
[]
end,
Constraint_types = collect_constraint_types(Schemas, Ctx),
Imports = [],
Imports@1 = case erlang:element(2, Constraint_types) of
true ->
[<<"gleam/string"/utf8>> | Imports];
false ->
Imports
end,
Imports@2 = case erlang:element(5, Constraint_types) of
true ->
[<<"gleam/list"/utf8>> | Imports@1];
false ->
Imports@1
end,
Imports@3 = case erlang:element(7, Constraint_types) of
true ->
[<<"gleam/dict.{type Dict}"/utf8>> | Imports@2];
false ->
Imports@2
end,
Imports@4 = case erlang:element(6, Constraint_types) of
true ->
[<<"gleam/int"/utf8>>, <<"gleam/float"/utf8>> | Imports@3];
false ->
Imports@3
end,
Needs_types = gleam@list:any(
Schemas,
fun(Entry) ->
{Name, Schema_ref} = Entry,
Guard_calls = collect_guard_calls(Name, Schema_ref, Ctx),
case gleam@list:is_empty(Guard_calls) of
true ->
false;
false ->
Resolved = case Schema_ref of
{inline, S} ->
{ok, S};
{reference, _, _} ->
oaspec@openapi@resolver:resolve_schema_ref(
Schema_ref,
erlang:element(2, Ctx)
)
end,
case Resolved of
{ok, {object_schema, _, _, _, _, _, _, _}} ->
true;
{ok, {all_of_schema, _, _}} ->
true;
_ ->
false
end
end
end
),
Imports@5 = case Needs_types of
true ->
[<<(erlang:element(5, erlang:element(3, Ctx)))/binary,
"/types"/utf8>> |
Imports@4];
false ->
Imports@4
end,
Needs_option = gleam@list:any(
Schemas,
fun(Entry@1) ->
{Name@1, Schema_ref@1} = Entry@1,
Guard_calls@1 = collect_guard_calls(Name@1, Schema_ref@1, Ctx),
gleam@list:any(
Guard_calls@1,
fun(Call) ->
{_, _, Is_required} = Call,
not Is_required
end
)
end
),
Imports@6 = case Needs_option of
true ->
[<<"gleam/option"/utf8>> | Imports@5];
false ->
Imports@5
end,
Sb = begin
_pipe = oaspec@util@string_extra:file_header(<<"0.6.0"/utf8>>),
oaspec@util@string_extra:imports(_pipe, Imports@6)
end,
Sb@2 = gleam@list:fold(
Schemas,
Sb,
fun(Sb@1, Entry@2) ->
{Name@2, Schema_ref@2} = Entry@2,
generate_guards_for_schema(Sb@1, Name@2, Schema_ref@2, Ctx)
end
),
Sb@4 = gleam@list:fold(
Schemas,
Sb@2,
fun(Sb@3, Entry@3) ->
{Name@3, Schema_ref@3} = Entry@3,
generate_composite_validator(Sb@3, Name@3, Schema_ref@3, Ctx)
end
),
oaspec@util@string_extra:to_string(Sb@4).
-file("src/oaspec/codegen/guards.gleam", 18).
?DOC(" Generate guard/validation functions from OpenAPI schemas that have constraints.\n").
-spec generate(oaspec@codegen@context:context()) -> list(oaspec@codegen@context:generated_file()).
generate(Ctx) ->
Content = generate_guards(Ctx),
case gleam_stdlib:contains_string(Content, <<"pub fn validate_"/utf8>>) of
true ->
[{generated_file, <<"guards.gleam"/utf8>>, Content, shared_target}];
false ->
[]
end.