Current section

Files

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

src/oaspec@codegen@decoders.erl

-module(oaspec@codegen@decoders).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/oaspec/codegen/decoders.gleam").
-export([generate/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/codegen/decoders.gleam", 788).
?DOC(" Generate decoder for a primitive type (String, Int, Float, Bool).\n").
-spec generate_primitive_decoder(
gleam@string_tree:string_tree(),
binary(),
binary(),
binary(),
binary()
) -> gleam@string_tree:string_tree().
generate_primitive_decoder(
Sb,
Fn_name,
Decoder_fn_name,
Gleam_type,
Decoder_expr
) ->
_pipe = Sb,
_pipe@1 = oaspec@util@string_extra:line(
_pipe,
<<<<<<<<"pub fn "/utf8, Decoder_fn_name/binary>>/binary,
"() -> decode.Decoder("/utf8>>/binary,
Gleam_type/binary>>/binary,
") {"/utf8>>
),
_pipe@2 = oaspec@util@string_extra:indent(_pipe@1, 1, Decoder_expr),
_pipe@3 = oaspec@util@string_extra:line(_pipe@2, <<"}"/utf8>>),
_pipe@4 = oaspec@util@string_extra:blank_line(_pipe@3),
_pipe@5 = oaspec@util@string_extra:line(
_pipe@4,
<<<<<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(json_string: String) -> Result("/utf8>>/binary,
Gleam_type/binary>>/binary,
", json.DecodeError) {"/utf8>>
),
_pipe@6 = oaspec@util@string_extra:indent(
_pipe@5,
1,
<<<<"json.parse(json_string, "/utf8, Decoder_expr/binary>>/binary,
")"/utf8>>
),
_pipe@7 = oaspec@util@string_extra:line(_pipe@6, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@7).
-file("src/oaspec/codegen/decoders.gleam", 1079).
?DOC(
" Get the discriminator value for a $ref.\n"
" OpenAPI discriminator.mapping is keyed by payload values, with $ref paths\n"
" as values: { \"dog\": \"#/components/schemas/Dog\" }.\n"
" Given a ref_name like \"Dog\", find the mapping key that points to it.\n"
" Falls back to ref_name if no explicit mapping exists.\n"
).
-spec get_discriminator_value(
oaspec@openapi@schema:discriminator(),
binary(),
binary()
) -> binary().
get_discriminator_value(Disc, Ref, Ref_name) ->
Found = begin
_pipe = maps:to_list(erlang:element(3, Disc)),
gleam@list:find(
_pipe,
fun(Entry) ->
{_, Target} = Entry,
(Target =:= Ref) orelse (oaspec@openapi@resolver:ref_to_name(
Target
)
=:= Ref_name)
end
)
end,
case Found of
{ok, {Disc_value, _}} ->
Disc_value;
{error, _} ->
Ref_name
end.
-file("src/oaspec/codegen/decoders.gleam", 1101).
?DOC(
" Convert a SchemaRef to a decoder expression string.\n"
" parent_name is used to resolve inline enum decoder names.\n"
).
-spec schema_ref_to_decoder(
oaspec@openapi@schema:schema_ref(),
binary(),
binary()
) -> binary().
schema_ref_to_decoder(Ref, Parent_name, Prop_name) ->
case Ref of
{inline, {string_schema, _, _, Enum_values, _, _, _}} when Enum_values =/= [] ->
Decoder_name = oaspec@util@naming:to_snake_case(
<<(oaspec@util@naming:schema_to_type_name(Parent_name))/binary,
(oaspec@util@naming:schema_to_type_name(Prop_name))/binary>>
),
<<Decoder_name/binary, "_decoder()"/utf8>>;
{inline, {array_schema, _, Items, _, _, _}} ->
Inner = schema_ref_to_decoder(Items, Parent_name, Prop_name),
<<<<"decode.list("/utf8, Inner/binary>>/binary, ")"/utf8>>;
_ ->
oaspec@codegen@schema_dispatch:decoder_expr(Ref)
end.
-file("src/oaspec/codegen/decoders.gleam", 1125).
?DOC(" Check if a SchemaRef has nullable: true.\n").
-spec schema_ref_is_nullable(
oaspec@openapi@schema:schema_ref(),
oaspec@codegen@context:context()
) -> boolean().
schema_ref_is_nullable(Ref, Ctx) ->
case Ref of
{inline, Schema} ->
oaspec@openapi@schema:is_nullable(Schema);
{reference, _, _} ->
case oaspec@openapi@resolver:resolve_schema_ref(
Ref,
oaspec@codegen@context:spec(Ctx)
) of
{ok, Resolved_schema} ->
oaspec@openapi@schema:is_nullable(Resolved_schema);
{error, _} ->
false
end
end.
-file("src/oaspec/codegen/decoders.gleam", 1138).
?DOC(" Get element at index from a list, or return a default.\n").
-spec list_at_or(list(binary()), integer(), binary()) -> binary().
list_at_or(Lst, Idx, Default) ->
case {Lst, Idx} of
{[], _} ->
Default;
{[Head | _], 0} ->
Head;
{[_ | Rest], N} ->
list_at_or(Rest, N - 1, Default)
end.
-file("src/oaspec/codegen/decoders.gleam", 1147).
?DOC(" Convert a SchemaRef to a qualified Gleam type string (with types. prefix for refs).\n").
-spec qualified_schema_ref_type(
oaspec@openapi@schema:schema_ref(),
oaspec@codegen@context:context()
) -> binary().
qualified_schema_ref_type(Ref, Ctx) ->
case Ref of
{inline, Schema} ->
oaspec@codegen@types:schema_to_gleam_type(Schema, Ctx);
_ ->
oaspec@codegen@schema_dispatch:schema_ref_qualified_type(Ref)
end.
-file("src/oaspec/codegen/decoders.gleam", 819).
?DOC(" Generate decoder for an ArraySchema.\n").
-spec generate_array_decoder(
gleam@string_tree:string_tree(),
binary(),
binary(),
binary(),
oaspec@openapi@schema:schema_ref(),
oaspec@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_array_decoder(Sb, Name, Fn_name, Decoder_fn_name, Items, Ctx) ->
Inner_decoder = schema_ref_to_decoder(Items, Name, <<""/utf8>>),
Inner_type = qualified_schema_ref_type(Items, Ctx),
Gleam_type = <<<<"List("/utf8, Inner_type/binary>>/binary, ")"/utf8>>,
_pipe = Sb,
_pipe@1 = oaspec@util@string_extra:line(
_pipe,
<<<<<<<<"pub fn "/utf8, Decoder_fn_name/binary>>/binary,
"() -> decode.Decoder("/utf8>>/binary,
Gleam_type/binary>>/binary,
") {"/utf8>>
),
_pipe@2 = oaspec@util@string_extra:indent(
_pipe@1,
1,
<<<<"decode.list("/utf8, Inner_decoder/binary>>/binary, ")"/utf8>>
),
_pipe@3 = oaspec@util@string_extra:line(_pipe@2, <<"}"/utf8>>),
_pipe@4 = oaspec@util@string_extra:blank_line(_pipe@3),
_pipe@5 = oaspec@util@string_extra:line(
_pipe@4,
<<<<<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(json_string: String) -> Result("/utf8>>/binary,
Gleam_type/binary>>/binary,
", json.DecodeError) {"/utf8>>
),
_pipe@6 = oaspec@util@string_extra:indent(
_pipe@5,
1,
<<<<"json.parse(json_string, "/utf8, Decoder_fn_name/binary>>/binary,
"())"/utf8>>
),
_pipe@7 = oaspec@util@string_extra:line(_pipe@6, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@7).
-file("src/oaspec/codegen/decoders.gleam", 1155).
?DOC(" Add a doc comment if description is present.\n").
-spec maybe_doc_comment(
gleam@string_tree:string_tree(),
gleam@option:option(binary())
) -> gleam@string_tree:string_tree().
maybe_doc_comment(Sb, Description) ->
case Description of
{some, Desc} ->
_pipe = Sb,
oaspec@util@string_extra:doc_comment(_pipe, Desc);
none ->
Sb
end.
-file("src/oaspec/codegen/decoders.gleam", 408).
?DOC(" Generate decoder for an ObjectSchema (properties, required, additionalProperties).\n").
-spec generate_object_decoder(
gleam@string_tree:string_tree(),
binary(),
binary(),
binary(),
binary(),
gleam@option:option(binary()),
gleam@dict:dict(binary(), oaspec@openapi@schema:schema_ref()),
list(binary()),
oaspec@openapi@schema:additional_properties(),
oaspec@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_object_decoder(
Sb,
Name,
Type_name,
Fn_name,
Decoder_fn_name,
Description,
Properties,
Required,
Additional_properties,
Ctx
) ->
Sb@1 = maybe_doc_comment(Sb, Description),
Sb@2 = begin
_pipe = Sb@1,
oaspec@util@string_extra:line(
_pipe,
<<<<<<<<"pub fn "/utf8, Decoder_fn_name/binary>>/binary,
"() -> decode.Decoder(types."/utf8>>/binary,
Type_name/binary>>/binary,
") {"/utf8>>
)
end,
Props = oaspec@codegen@ir_build:sorted_entries(Properties),
Deduped_names = oaspec@openapi@dedup:dedup_property_names(
gleam@list:map(Props, fun(E) -> erlang:element(1, E) end)
),
Sb@4 = gleam@list:index_fold(
Props,
Sb@2,
fun(Sb@3, Entry, Idx) ->
{Prop_name, Prop_ref} = Entry,
Field_name = list_at_or(
Deduped_names,
Idx,
oaspec@util@naming:to_snake_case(Prop_name)
),
Is_write_only = oaspec@codegen@types:schema_ref_is_write_only(
Prop_ref,
Ctx
),
Is_required = gleam@list:contains(Required, Prop_name) andalso not Is_write_only,
Field_decoder = schema_ref_to_decoder(Prop_ref, Name, Prop_name),
Is_nullable_schema = schema_ref_is_nullable(Prop_ref, Ctx),
Effective_decoder = case Is_nullable_schema of
true ->
<<<<"decode.optional("/utf8, Field_decoder/binary>>/binary,
")"/utf8>>;
false ->
Field_decoder
end,
case Is_required of
true ->
_pipe@1 = Sb@3,
oaspec@util@string_extra:indent(
_pipe@1,
1,
<<<<<<<<<<<<"use "/utf8, Field_name/binary>>/binary,
" <- decode.field(\""/utf8>>/binary,
Prop_name/binary>>/binary,
"\", "/utf8>>/binary,
Effective_decoder/binary>>/binary,
")"/utf8>>
);
false ->
case Is_nullable_schema of
true ->
_pipe@2 = Sb@3,
oaspec@util@string_extra:indent(
_pipe@2,
1,
<<<<<<<<<<<<"use "/utf8, Field_name/binary>>/binary,
" <- decode.optional_field(\""/utf8>>/binary,
Prop_name/binary>>/binary,
"\", option.None, "/utf8>>/binary,
Effective_decoder/binary>>/binary,
")"/utf8>>
);
false ->
_pipe@3 = Sb@3,
oaspec@util@string_extra:indent(
_pipe@3,
1,
<<<<<<<<<<<<"use "/utf8, Field_name/binary>>/binary,
" <- decode.optional_field(\""/utf8>>/binary,
Prop_name/binary>>/binary,
"\", option.None, decode.optional("/utf8>>/binary,
Field_decoder/binary>>/binary,
"))"/utf8>>
)
end
end
end
),
Known_keys_expr = case gleam@list:is_empty(Props) of
true ->
<<"[]"/utf8>>;
false ->
<<<<"["/utf8,
(oaspec@util@string_extra:join_with(
gleam@list:map(
Props,
fun(Entry@1) ->
{Prop_name@1, _} = Entry@1,
<<<<"\""/utf8, Prop_name@1/binary>>/binary,
"\""/utf8>>
end
),
<<", "/utf8>>
))/binary>>/binary,
"]"/utf8>>
end,
Sb@5 = case Additional_properties of
{typed, Ap_ref} ->
Inner_decoder = schema_ref_to_decoder(
Ap_ref,
Name,
<<"additional_properties"/utf8>>
),
_pipe@4 = Sb@4,
_pipe@5 = oaspec@util@string_extra:indent(
_pipe@4,
1,
<<"use all_props <- decode.then(decode.dict(decode.string, decode.new_primitive_decoder(\"Dynamic\", fn(x) { Ok(x) })))"/utf8>>
),
_pipe@6 = oaspec@util@string_extra:indent(
_pipe@5,
1,
<<<<"let extra_props = dict.drop(all_props, "/utf8,
Known_keys_expr/binary>>/binary,
")"/utf8>>
),
_pipe@7 = oaspec@util@string_extra:indent(
_pipe@6,
1,
<<"let additional_properties_result = dict.fold(extra_props, Ok(dict.new()), fn(acc, k, v) {"/utf8>>
),
_pipe@8 = oaspec@util@string_extra:indent(
_pipe@7,
2,
<<"case acc {"/utf8>>
),
_pipe@9 = oaspec@util@string_extra:indent(
_pipe@8,
3,
<<"Ok(decoded_acc) ->"/utf8>>
),
_pipe@10 = oaspec@util@string_extra:indent(
_pipe@9,
4,
<<<<"case decode.run(v, "/utf8, Inner_decoder/binary>>/binary,
") {"/utf8>>
),
_pipe@11 = oaspec@util@string_extra:indent(
_pipe@10,
5,
<<"Ok(decoded) -> Ok(dict.insert(decoded_acc, k, decoded))"/utf8>>
),
_pipe@12 = oaspec@util@string_extra:indent(
_pipe@11,
5,
<<"Error(_) -> Error(Nil)"/utf8>>
),
_pipe@13 = oaspec@util@string_extra:indent(
_pipe@12,
4,
<<"}"/utf8>>
),
_pipe@14 = oaspec@util@string_extra:indent(
_pipe@13,
3,
<<"Error(_) -> Error(Nil)"/utf8>>
),
_pipe@15 = oaspec@util@string_extra:indent(
_pipe@14,
2,
<<"}"/utf8>>
),
_pipe@16 = oaspec@util@string_extra:indent(
_pipe@15,
1,
<<"})"/utf8>>
),
_pipe@17 = oaspec@util@string_extra:indent(
_pipe@16,
1,
<<"use additional_properties <- decode.then(case additional_properties_result {"/utf8>>
),
_pipe@18 = oaspec@util@string_extra:indent(
_pipe@17,
2,
<<"Ok(decoded) -> decode.success(decoded)"/utf8>>
),
_pipe@19 = oaspec@util@string_extra:indent(
_pipe@18,
2,
<<"Error(_) -> decode.failure(dict.new(), \"additionalProperties\")"/utf8>>
),
oaspec@util@string_extra:indent(_pipe@19, 1, <<"})"/utf8>>);
untyped ->
_pipe@20 = Sb@4,
_pipe@21 = oaspec@util@string_extra:indent(
_pipe@20,
1,
<<"use all_props <- decode.then(decode.dict(decode.string, decode.new_primitive_decoder(\"Dynamic\", fn(x) { Ok(x) })))"/utf8>>
),
oaspec@util@string_extra:indent(
_pipe@21,
1,
<<<<"let additional_properties = dict.drop(all_props, "/utf8,
Known_keys_expr/binary>>/binary,
")"/utf8>>
);
forbidden ->
Sb@4;
unspecified ->
Sb@4
end,
Param_names = gleam@list:index_map(
Props,
fun(Entry@2, Idx@1) ->
{Prop_name@2, _} = Entry@2,
Field_name@1 = list_at_or(
Deduped_names,
Idx@1,
oaspec@util@naming:to_snake_case(Prop_name@2)
),
<<<<Field_name@1/binary, ": "/utf8>>/binary, Field_name@1/binary>>
end
),
Param_names@1 = case Additional_properties of
{typed, _} ->
lists:append(
Param_names,
[<<"additional_properties: additional_properties"/utf8>>]
);
untyped ->
lists:append(
Param_names,
[<<"additional_properties: additional_properties"/utf8>>]
);
forbidden ->
Param_names;
unspecified ->
Param_names
end,
Sb@6 = begin
_pipe@22 = Sb@5,
oaspec@util@string_extra:indent(
_pipe@22,
1,
<<<<<<<<"decode.success(types."/utf8, Type_name/binary>>/binary,
"("/utf8>>/binary,
(oaspec@util@string_extra:join_with(
Param_names@1,
<<", "/utf8>>
))/binary>>/binary,
"))"/utf8>>
)
end,
Sb@7 = begin
_pipe@23 = Sb@6,
_pipe@24 = oaspec@util@string_extra:line(_pipe@23, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@24)
end,
Sb@8 = begin
_pipe@25 = Sb@7,
_pipe@26 = oaspec@util@string_extra:line(
_pipe@25,
<<<<<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(json_string: String) -> Result(types."/utf8>>/binary,
Type_name/binary>>/binary,
", json.DecodeError) {"/utf8>>
),
_pipe@27 = oaspec@util@string_extra:indent(
_pipe@26,
1,
<<<<"json.parse(json_string, "/utf8, Decoder_fn_name/binary>>/binary,
"())"/utf8>>
),
_pipe@28 = oaspec@util@string_extra:line(_pipe@27, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@28)
end,
List_fn_name = <<Fn_name/binary, "_list"/utf8>>,
List_decoder_fn_name = <<Decoder_fn_name/binary, "_list"/utf8>>,
_pipe@29 = Sb@8,
_pipe@30 = oaspec@util@string_extra:line(
_pipe@29,
<<<<<<<<"pub fn "/utf8, List_decoder_fn_name/binary>>/binary,
"() -> decode.Decoder(List(types."/utf8>>/binary,
Type_name/binary>>/binary,
")) {"/utf8>>
),
_pipe@31 = oaspec@util@string_extra:indent(
_pipe@30,
1,
<<<<"decode.list("/utf8, Decoder_fn_name/binary>>/binary, "())"/utf8>>
),
_pipe@32 = oaspec@util@string_extra:line(_pipe@31, <<"}"/utf8>>),
_pipe@33 = oaspec@util@string_extra:blank_line(_pipe@32),
_pipe@34 = oaspec@util@string_extra:line(
_pipe@33,
<<<<<<<<"pub fn "/utf8, List_fn_name/binary>>/binary,
"(json_string: String) -> Result(List(types."/utf8>>/binary,
Type_name/binary>>/binary,
"), json.DecodeError) {"/utf8>>
),
_pipe@35 = oaspec@util@string_extra:indent(
_pipe@34,
1,
<<<<"json.parse(json_string, "/utf8, List_decoder_fn_name/binary>>/binary,
"())"/utf8>>
),
_pipe@36 = oaspec@util@string_extra:line(_pipe@35, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@36).
-file("src/oaspec/codegen/decoders.gleam", 640).
?DOC(" Generate decoder for a string enum schema.\n").
-spec generate_enum_decoder(
gleam@string_tree:string_tree(),
binary(),
binary(),
binary(),
gleam@option:option(binary()),
list(binary())
) -> gleam@string_tree:string_tree().
generate_enum_decoder(
Sb,
Type_name,
Fn_name,
Decoder_fn_name,
Description,
Enum_values
) ->
Sb@1 = maybe_doc_comment(Sb, Description),
Sb@2 = begin
_pipe = Sb@1,
_pipe@1 = oaspec@util@string_extra:line(
_pipe,
<<<<<<<<"pub fn "/utf8, Decoder_fn_name/binary>>/binary,
"() -> decode.Decoder(types."/utf8>>/binary,
Type_name/binary>>/binary,
") {"/utf8>>
),
_pipe@2 = oaspec@util@string_extra:indent(
_pipe@1,
1,
<<"use value <- decode.then(decode.string)"/utf8>>
),
oaspec@util@string_extra:indent(_pipe@2, 1, <<"case value {"/utf8>>)
end,
Deduped_variants = oaspec@openapi@dedup:dedup_enum_variants(Enum_values),
Sb@4 = gleam@list:index_fold(
Enum_values,
Sb@2,
fun(Sb@3, Value, Idx) ->
Variant_suffix = list_at_or(
Deduped_variants,
Idx,
oaspec@util@naming:to_pascal_case(Value)
),
Variant = <<(oaspec@util@naming:schema_to_type_name(Type_name))/binary,
Variant_suffix/binary>>,
_pipe@3 = Sb@3,
oaspec@util@string_extra:indent(
_pipe@3,
2,
<<<<<<<<"\""/utf8, Value/binary>>/binary,
"\" -> decode.success(types."/utf8>>/binary,
Variant/binary>>/binary,
")"/utf8>>
)
end
),
First_variant_suffix = list_at_or(Deduped_variants, 0, case Enum_values of
[First | _] ->
oaspec@util@naming:to_pascal_case(First);
[] ->
<<"Unknown"/utf8>>
end),
_pipe@4 = Sb@4,
_pipe@5 = oaspec@util@string_extra:indent(
_pipe@4,
2,
<<<<<<<<<<"_ -> decode.failure(types."/utf8,
(oaspec@util@naming:schema_to_type_name(Type_name))/binary>>/binary,
First_variant_suffix/binary>>/binary,
", \""/utf8>>/binary,
Type_name/binary>>/binary,
": unknown variant \" <> value)"/utf8>>
),
_pipe@6 = oaspec@util@string_extra:indent(_pipe@5, 1, <<"}"/utf8>>),
_pipe@7 = oaspec@util@string_extra:line(_pipe@6, <<"}"/utf8>>),
_pipe@8 = oaspec@util@string_extra:blank_line(_pipe@7),
_pipe@9 = oaspec@util@string_extra:line(
_pipe@8,
<<<<<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(json_string: String) -> Result(types."/utf8>>/binary,
Type_name/binary>>/binary,
", json.DecodeError) {"/utf8>>
),
_pipe@10 = oaspec@util@string_extra:indent(
_pipe@9,
1,
<<<<"json.parse(json_string, "/utf8, Decoder_fn_name/binary>>/binary,
"())"/utf8>>
),
_pipe@11 = oaspec@util@string_extra:line(_pipe@10, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@11).
-file("src/oaspec/codegen/decoders.gleam", 707).
?DOC(" Generate decoder for an anyOf (inclusive union) schema.\n").
-spec generate_anyof_decoder(
gleam@string_tree:string_tree(),
binary(),
binary(),
binary(),
gleam@option:option(binary()),
list(oaspec@openapi@schema:schema_ref())
) -> gleam@string_tree:string_tree().
generate_anyof_decoder(
Sb,
Type_name,
Fn_name,
Decoder_fn_name,
Description,
Schemas
) ->
Sb@1 = maybe_doc_comment(Sb, Description),
Variant_fields = gleam@list:map(Schemas, fun(S_ref) -> case S_ref of
{reference, _, Ref_name} ->
Field_name = oaspec@util@naming:to_snake_case(Ref_name),
Decoder_name = <<<<"decode_"/utf8,
(oaspec@util@naming:to_snake_case(Ref_name))/binary>>/binary,
"_decoder"/utf8>>,
{Field_name, Decoder_name, Ref_name};
{inline, _} ->
{<<"unknown"/utf8>>,
<<"decode.string"/utf8>>,
<<"Unknown"/utf8>>}
end end),
Sb@2 = begin
_pipe = Sb@1,
oaspec@util@string_extra:line(
_pipe,
<<<<<<<<"pub fn "/utf8, Decoder_fn_name/binary>>/binary,
"() -> decode.Decoder(types."/utf8>>/binary,
Type_name/binary>>/binary,
") {"/utf8>>
)
end,
Sb@4 = gleam@list:fold(
Variant_fields,
Sb@2,
fun(Sb@3, Field) ->
{Field_name@1, Decoder_name@1, _} = Field,
_pipe@1 = Sb@3,
oaspec@util@string_extra:indent(
_pipe@1,
1,
<<<<<<<<"use "/utf8, Field_name@1/binary>>/binary,
" <- decode.then(decode.one_of("/utf8>>/binary,
Decoder_name@1/binary>>/binary,
"() |> decode.map(option.Some), or: [decode.success(option.None)]))"/utf8>>
)
end
),
Field_assignments = gleam@list:map(
Variant_fields,
fun(F) ->
{Field_name@2, _, _} = F,
<<<<Field_name@2/binary, ": "/utf8>>/binary, Field_name@2/binary>>
end
),
_pipe@2 = Sb@4,
_pipe@3 = oaspec@util@string_extra:indent(
_pipe@2,
1,
<<<<<<<<"decode.success(types."/utf8, Type_name/binary>>/binary,
"("/utf8>>/binary,
(gleam@string:join(Field_assignments, <<", "/utf8>>))/binary>>/binary,
"))"/utf8>>
),
_pipe@4 = oaspec@util@string_extra:line(_pipe@3, <<"}"/utf8>>),
_pipe@5 = oaspec@util@string_extra:blank_line(_pipe@4),
_pipe@6 = oaspec@util@string_extra:line(
_pipe@5,
<<<<<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(json_string: String) -> Result(types."/utf8>>/binary,
Type_name/binary>>/binary,
", json.DecodeError) {"/utf8>>
),
_pipe@7 = oaspec@util@string_extra:indent(
_pipe@6,
1,
<<<<"json.parse(json_string, "/utf8, Decoder_fn_name/binary>>/binary,
"())"/utf8>>
),
_pipe@8 = oaspec@util@string_extra:line(_pipe@7, <<"}"/utf8>>),
oaspec@util@string_extra:blank_line(_pipe@8).
-file("src/oaspec/codegen/decoders.gleam", 856).
?DOC(
" Generate decoder for oneOf/anyOf union types.\n"
" With discriminator: decode based on discriminator field value.\n"
" Without discriminator: try each variant decoder in order.\n"
).
-spec generate_oneof_decoder(
gleam@string_tree:string_tree(),
binary(),
binary(),
binary(),
binary(),
gleam@option:option(binary()),
list(oaspec@openapi@schema:schema_ref()),
gleam@option:option(oaspec@openapi@schema:discriminator()),
oaspec@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_oneof_decoder(
Sb,
_,
Type_name,
Fn_name,
Decoder_fn_name,
Description,
Schemas,
Discriminator,
_
) ->
All_refs = gleam@list:all(Schemas, fun(S) -> case S of
{reference, _, _} ->
true;
_ ->
false
end end),
case All_refs of
false ->
Sb;
true ->
Sb@1 = maybe_doc_comment(Sb, Description),
case Discriminator of
{some, Disc} ->
Sb@2 = begin
_pipe = Sb@1,
_pipe@1 = oaspec@util@string_extra:line(
_pipe,
<<<<<<<<"pub fn "/utf8, Decoder_fn_name/binary>>/binary,
"() -> decode.Decoder(types."/utf8>>/binary,
Type_name/binary>>/binary,
") {"/utf8>>
),
_pipe@2 = oaspec@util@string_extra:indent(
_pipe@1,
1,
<<<<"use disc_value <- decode.field(\""/utf8,
(erlang:element(2, Disc))/binary>>/binary,
"\", decode.string)"/utf8>>
),
oaspec@util@string_extra:indent(
_pipe@2,
1,
<<"case disc_value {"/utf8>>
)
end,
Sb@4 = gleam@list:fold(
Schemas,
Sb@2,
fun(Sb@3, S_ref) -> case S_ref of
{reference, Ref, Name} ->
Ref_name = Name,
Variant_type = oaspec@util@naming:schema_to_type_name(
Ref_name
),
Variant_name = <<Type_name/binary,
Variant_type/binary>>,
Variant_decoder = <<(oaspec@util@naming:to_snake_case(
Ref_name
))/binary,
"_decoder()"/utf8>>,
Disc_value = get_discriminator_value(
Disc,
Ref,
Ref_name
),
_pipe@3 = Sb@3,
_pipe@4 = oaspec@util@string_extra:indent(
_pipe@3,
2,
<<<<"\""/utf8, Disc_value/binary>>/binary,
"\" -> {"/utf8>>
),
_pipe@5 = oaspec@util@string_extra:indent(
_pipe@4,
3,
<<<<"use inner <- decode.then("/utf8,
Variant_decoder/binary>>/binary,
")"/utf8>>
),
_pipe@6 = oaspec@util@string_extra:indent(
_pipe@5,
3,
<<<<"decode.success(types."/utf8,
Variant_name/binary>>/binary,
"(inner))"/utf8>>
),
oaspec@util@string_extra:indent(
_pipe@6,
2,
<<"}"/utf8>>
);
_ ->
Sb@3
end end
),
First_ref_decoder = case Schemas of
[{reference, _, Name@1} | _] ->
Ref_name@1 = Name@1,
<<(oaspec@util@naming:to_snake_case(Ref_name@1))/binary,
"_decoder()"/utf8>>;
_ ->
<<"decode.string"/utf8>>
end,
First_variant_name = case Schemas of
[{reference, _, Name@2} | _] ->
Ref_name@2 = Name@2,
Variant_type@1 = oaspec@util@naming:schema_to_type_name(
Ref_name@2
),
<<<<"types."/utf8, Type_name/binary>>/binary,
Variant_type@1/binary>>;
_ ->
<<"types."/utf8, Type_name/binary>>
end,
Sb@5 = begin
_pipe@7 = Sb@4,
_pipe@8 = oaspec@util@string_extra:indent(
_pipe@7,
2,
<<"_ -> {"/utf8>>
),
_pipe@9 = oaspec@util@string_extra:indent(
_pipe@8,
3,
<<<<"use v <- decode.then("/utf8,
First_ref_decoder/binary>>/binary,
")"/utf8>>
),
_pipe@10 = oaspec@util@string_extra:indent(
_pipe@9,
3,
<<<<<<<<"decode.failure("/utf8,
First_variant_name/binary>>/binary,
"(v), \""/utf8>>/binary,
Type_name/binary>>/binary,
"\")"/utf8>>
),
_pipe@11 = oaspec@util@string_extra:indent(
_pipe@10,
2,
<<"}"/utf8>>
),
_pipe@12 = oaspec@util@string_extra:indent(
_pipe@11,
1,
<<"}"/utf8>>
),
_pipe@13 = oaspec@util@string_extra:line(
_pipe@12,
<<"}"/utf8>>
),
oaspec@util@string_extra:blank_line(_pipe@13)
end,
_pipe@14 = Sb@5,
_pipe@15 = oaspec@util@string_extra:line(
_pipe@14,
<<<<<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(json_string: String) -> Result(types."/utf8>>/binary,
Type_name/binary>>/binary,
", json.DecodeError) {"/utf8>>
),
_pipe@16 = oaspec@util@string_extra:indent(
_pipe@15,
1,
<<<<"json.parse(json_string, "/utf8,
Decoder_fn_name/binary>>/binary,
"())"/utf8>>
),
_pipe@17 = oaspec@util@string_extra:line(
_pipe@16,
<<"}"/utf8>>
),
oaspec@util@string_extra:blank_line(_pipe@17);
none ->
Ref_variants = gleam@list:filter_map(
Schemas,
fun(S_ref@1) -> case S_ref@1 of
{reference, _, Name@3} ->
Ref_name@3 = Name@3,
{ok, Ref_name@3};
_ ->
{error, nil}
end end
),
Sb@6 = begin
_pipe@18 = Sb@1,
oaspec@util@string_extra:line(
_pipe@18,
<<<<<<<<"pub fn "/utf8, Decoder_fn_name/binary>>/binary,
"() -> decode.Decoder(types."/utf8>>/binary,
Type_name/binary>>/binary,
") {"/utf8>>
)
end,
Sb@10 = case Ref_variants of
[] ->
_pipe@19 = Sb@6,
oaspec@util@string_extra:indent(
_pipe@19,
1,
<<<<<<<<"decode.failure(types."/utf8,
Type_name/binary>>/binary,
", \""/utf8>>/binary,
Type_name/binary>>/binary,
"\")"/utf8>>
);
[First | Rest] ->
First_variant_type = oaspec@util@naming:schema_to_type_name(
First
),
First_decoder = <<(oaspec@util@naming:to_snake_case(
First
))/binary,
"_decoder()"/utf8>>,
Sb@7 = begin
_pipe@20 = Sb@6,
oaspec@util@string_extra:indent(
_pipe@20,
1,
<<<<<<<<<<"decode.one_of("/utf8,
First_decoder/binary>>/binary,
" |> decode.map(types."/utf8>>/binary,
Type_name/binary>>/binary,
First_variant_type/binary>>/binary,
"), ["/utf8>>
)
end,
Sb@9 = gleam@list:fold(
Rest,
Sb@7,
fun(Sb@8, Ref_name@4) ->
Variant_type@2 = oaspec@util@naming:schema_to_type_name(
Ref_name@4
),
Decoder = <<(oaspec@util@naming:to_snake_case(
Ref_name@4
))/binary,
"_decoder()"/utf8>>,
_pipe@21 = Sb@8,
oaspec@util@string_extra:indent(
_pipe@21,
2,
<<<<<<<<Decoder/binary,
" |> decode.map(types."/utf8>>/binary,
Type_name/binary>>/binary,
Variant_type@2/binary>>/binary,
"),"/utf8>>
)
end
),
_pipe@22 = Sb@9,
oaspec@util@string_extra:indent(
_pipe@22,
1,
<<"])"/utf8>>
)
end,
Sb@11 = begin
_pipe@23 = Sb@10,
_pipe@24 = oaspec@util@string_extra:line(
_pipe@23,
<<"}"/utf8>>
),
oaspec@util@string_extra:blank_line(_pipe@24)
end,
_pipe@25 = Sb@11,
_pipe@26 = oaspec@util@string_extra:line(
_pipe@25,
<<<<<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(json_string: String) -> Result(types."/utf8>>/binary,
Type_name/binary>>/binary,
", json.DecodeError) {"/utf8>>
),
_pipe@27 = oaspec@util@string_extra:indent(
_pipe@26,
1,
<<<<"json.parse(json_string, "/utf8,
Decoder_fn_name/binary>>/binary,
"())"/utf8>>
),
_pipe@28 = oaspec@util@string_extra:line(
_pipe@27,
<<"}"/utf8>>
),
oaspec@util@string_extra:blank_line(_pipe@28)
end
end.
-file("src/oaspec/codegen/decoders.gleam", 266).
?DOC(" Generate decoder functions for a schema.\n").
-spec generate_decoder(
gleam@string_tree:string_tree(),
binary(),
oaspec@openapi@schema:schema_ref(),
oaspec@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_decoder(Sb, Name, Schema_ref, Ctx) ->
Type_name = oaspec@util@naming:schema_to_type_name(Name),
Fn_name = <<"decode_"/utf8,
(oaspec@util@naming:to_snake_case(Name))/binary>>,
Decoder_fn_name = <<(oaspec@util@naming:to_snake_case(Name))/binary,
"_decoder"/utf8>>,
case Schema_ref of
{inline,
{object_schema,
Metadata,
Properties,
Required,
Additional_properties,
_,
_}} ->
generate_object_decoder(
Sb,
Name,
Type_name,
Fn_name,
Decoder_fn_name,
erlang:element(2, Metadata),
Properties,
Required,
Additional_properties,
Ctx
);
{inline, {string_schema, Metadata@1, _, Enum_values, _, _, _}} when Enum_values =/= [] ->
generate_enum_decoder(
Sb,
Type_name,
Fn_name,
Decoder_fn_name,
erlang:element(2, Metadata@1),
Enum_values
);
{inline, {all_of_schema, Metadata@2, Schemas}} ->
Merged = oaspec@codegen@types:merge_allof_schemas(Schemas, Ctx),
Merged_schema = {inline,
{object_schema,
Metadata@2,
erlang:element(2, Merged),
erlang:element(3, Merged),
erlang:element(4, Merged),
none,
none}},
generate_decoder(Sb, Name, Merged_schema, Ctx);
{inline, {one_of_schema, Metadata@3, Schemas@1, Discriminator}} ->
generate_oneof_decoder(
Sb,
Name,
Type_name,
Fn_name,
Decoder_fn_name,
erlang:element(2, Metadata@3),
Schemas@1,
Discriminator,
Ctx
);
{inline, {any_of_schema, Metadata@4, Schemas@2, _}} ->
generate_anyof_decoder(
Sb,
Type_name,
Fn_name,
Decoder_fn_name,
erlang:element(2, Metadata@4),
Schemas@2
);
{inline, {string_schema, Metadata@5, _, [], _, _, _}} ->
{Gleam_type, Decoder_expr} = case erlang:element(3, Metadata@5) of
true ->
{<<"Option(String)"/utf8>>,
<<"decode.optional(decode.string)"/utf8>>};
false ->
{<<"String"/utf8>>, <<"decode.string"/utf8>>}
end,
generate_primitive_decoder(
Sb,
Fn_name,
Decoder_fn_name,
Gleam_type,
Decoder_expr
);
{inline, {integer_schema, Metadata@6, _, _, _, _, _, _}} ->
{Gleam_type@1, Decoder_expr@1} = case erlang:element(3, Metadata@6) of
true ->
{<<"Option(Int)"/utf8>>,
<<"decode.optional(decode.int)"/utf8>>};
false ->
{<<"Int"/utf8>>, <<"decode.int"/utf8>>}
end,
generate_primitive_decoder(
Sb,
Fn_name,
Decoder_fn_name,
Gleam_type@1,
Decoder_expr@1
);
{inline, {number_schema, Metadata@7, _, _, _, _, _, _}} ->
{Gleam_type@2, Decoder_expr@2} = case erlang:element(3, Metadata@7) of
true ->
{<<"Option(Float)"/utf8>>,
<<"decode.optional(decode.float)"/utf8>>};
false ->
{<<"Float"/utf8>>, <<"decode.float"/utf8>>}
end,
generate_primitive_decoder(
Sb,
Fn_name,
Decoder_fn_name,
Gleam_type@2,
Decoder_expr@2
);
{inline, {boolean_schema, Metadata@8}} ->
{Gleam_type@3, Decoder_expr@3} = case erlang:element(3, Metadata@8) of
true ->
{<<"Option(Bool)"/utf8>>,
<<"decode.optional(decode.bool)"/utf8>>};
false ->
{<<"Bool"/utf8>>, <<"decode.bool"/utf8>>}
end,
generate_primitive_decoder(
Sb,
Fn_name,
Decoder_fn_name,
Gleam_type@3,
Decoder_expr@3
);
{inline, {array_schema, _, Items, _, _, _}} ->
generate_array_decoder(
Sb,
Name,
Fn_name,
Decoder_fn_name,
Items,
Ctx
);
_ ->
Sb
end.
-file("src/oaspec/codegen/decoders.gleam", 224).
?DOC(" Generate decoder for an anonymous schema with a composed name.\n").
-spec generate_anonymous_schema_decoder(
gleam@string_tree:string_tree(),
binary(),
binary(),
oaspec@openapi@schema:schema_object(),
oaspec@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_anonymous_schema_decoder(Sb, Op_id, Suffix, Schema_obj, Ctx) ->
Name = <<<<(oaspec@util@naming:to_snake_case(Op_id))/binary, "_"/utf8>>/binary,
(oaspec@util@naming:to_snake_case(Suffix))/binary>>,
Schema_ref = {inline, Schema_obj},
generate_decoder(Sb, Name, Schema_ref, Ctx).
-file("src/oaspec/codegen/decoders.gleam", 150).
?DOC(" Generate decoders for inline response schemas.\n").
-spec generate_anonymous_response_decoders(
gleam@string_tree:string_tree(),
binary(),
oaspec@openapi@spec:operation(oaspec@openapi@spec:resolved()),
oaspec@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_anonymous_response_decoders(Sb, Op_id, Operation, Ctx) ->
Responses = oaspec@util@http:sort_response_entries(
maps:to_list(erlang:element(8, Operation))
),
gleam@list:fold(
Responses,
Sb,
fun(Sb@1, Entry) ->
{Status_code, Ref_or_response} = Entry,
case Ref_or_response of
{value, Response} ->
Content_entries = oaspec@codegen@ir_build:sorted_entries(
erlang:element(3, Response)
),
case Content_entries of
[{_, Media_type} | _] ->
case erlang:element(2, Media_type) of
{some, {inline, Schema_obj}} ->
Filtered_schema = oaspec@codegen@types:filter_write_only_properties(
Schema_obj,
Ctx
),
Suffix = <<"Response"/utf8,
(oaspec@util@http:status_code_suffix(
Status_code
))/binary>>,
generate_anonymous_schema_decoder(
Sb@1,
Op_id,
Suffix,
Filtered_schema,
Ctx
);
_ ->
Sb@1
end;
_ ->
Sb@1
end;
{ref, _} ->
Sb@1
end
end
).
-file("src/oaspec/codegen/decoders.gleam", 189).
?DOC(" Generate decoder for an inline requestBody schema.\n").
-spec generate_anonymous_request_body_decoder(
gleam@string_tree:string_tree(),
binary(),
oaspec@openapi@spec:operation(oaspec@openapi@spec:resolved()),
oaspec@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_anonymous_request_body_decoder(Sb, Op_id, Operation, Ctx) ->
case erlang:element(7, Operation) of
{some, {value, Rb}} ->
Content_entries = oaspec@codegen@ir_build:sorted_entries(
erlang:element(3, Rb)
),
case Content_entries of
[{_, Media_type} | _] ->
case erlang:element(2, Media_type) of
{some, {inline, Schema_obj}} ->
Filtered_schema = oaspec@codegen@types:filter_read_only_properties(
Schema_obj,
Ctx
),
generate_anonymous_schema_decoder(
Sb,
Op_id,
<<"RequestBody"/utf8>>,
Filtered_schema,
Ctx
);
_ ->
Sb
end;
_ ->
Sb
end;
{some, {ref, _}} ->
Sb;
none ->
Sb
end.
-file("src/oaspec/codegen/decoders.gleam", 137).
?DOC(" Generate decoders for anonymous inline schemas (response/requestBody).\n").
-spec generate_anonymous_decoders(
gleam@string_tree:string_tree(),
oaspec@codegen@context:context(),
list({binary(),
oaspec@openapi@spec:operation(oaspec@openapi@spec:resolved()),
binary(),
oaspec@openapi@spec:http_method()})
) -> gleam@string_tree:string_tree().
generate_anonymous_decoders(Sb, Ctx, Operations) ->
gleam@list:fold(
Operations,
Sb,
fun(Sb@1, Op) ->
{Op_id, Operation, _, _} = Op,
Sb@2 = generate_anonymous_response_decoders(
Sb@1,
Op_id,
Operation,
Ctx
),
generate_anonymous_request_body_decoder(Sb@2, Op_id, Operation, Ctx)
end
).
-file("src/oaspec/codegen/decoders.gleam", 237).
?DOC(" Generate inline enum decoders found in object/allOf properties.\n").
-spec generate_inline_enum_decoders(
gleam@string_tree:string_tree(),
binary(),
oaspec@openapi@schema:schema_ref(),
oaspec@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_inline_enum_decoders(Sb, Parent_name, Schema_ref, Ctx) ->
Props = case Schema_ref of
{inline, {object_schema, _, Properties, _, _, _, _}} ->
oaspec@codegen@ir_build:sorted_entries(Properties);
{inline, {all_of_schema, _, Schemas}} ->
oaspec@codegen@ir_build:sorted_entries(
erlang:element(
2,
oaspec@codegen@allof_merge:merge_allof_schemas(Schemas, Ctx)
)
);
_ ->
[]
end,
gleam@list:fold(
Props,
Sb,
fun(Sb@1, Entry) ->
{Prop_name, Prop_ref} = Entry,
case Prop_ref of
{inline, {string_schema, _, _, Enum_values, _, _, _}} when Enum_values =/= [] ->
Enum_name = <<(oaspec@util@naming:schema_to_type_name(
Parent_name
))/binary,
(oaspec@util@naming:schema_to_type_name(Prop_name))/binary>>,
generate_decoder(Sb@1, Enum_name, Prop_ref, Ctx);
_ ->
Sb@1
end
end
).
-file("src/oaspec/codegen/decoders.gleam", 47).
?DOC(" Generate JSON decoders for all component schemas and anonymous types.\n").
-spec generate_decoders(
oaspec@codegen@context:context(),
list({binary(),
oaspec@openapi@spec:operation(oaspec@openapi@spec:resolved()),
binary(),
oaspec@openapi@spec:http_method()})
) -> binary().
generate_decoders(Ctx, Operations) ->
Schemas = case erlang:element(5, oaspec@codegen@context:spec(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,
Needs_option = gleam@list:any(
Schemas,
fun(Entry) ->
{_, Schema_ref} = Entry,
oaspec@codegen@types:schema_has_optional_fields(Schema_ref, Ctx)
end
),
Needs_dict = gleam@list:any(
Schemas,
fun(Entry@1) ->
{_, Schema_ref@1} = Entry@1,
oaspec@codegen@types:schema_has_additional_properties(
Schema_ref@1,
Ctx
)
end
),
Needs_types = gleam@list:any(
Schemas,
fun(Entry@2) ->
{_, Schema_ref@2} = Entry@2,
case Schema_ref@2 of
{inline, {object_schema, _, _, _, _, _, _}} ->
true;
{inline, {all_of_schema, _, _}} ->
true;
{inline, {one_of_schema, _, _, _}} ->
true;
{inline, {any_of_schema, _, _, _}} ->
true;
{inline, {string_schema, _, _, Enum_values, _, _, _}} when Enum_values =/= [] ->
true;
_ ->
false
end
end
),
Base_imports = case Needs_dict of
true ->
[<<"gleam/dict"/utf8>>,
<<"gleam/dynamic/decode"/utf8>>,
<<"gleam/json"/utf8>>];
false ->
[<<"gleam/dynamic/decode"/utf8>>, <<"gleam/json"/utf8>>]
end,
Base_imports@1 = case Needs_types of
true ->
lists:append(
Base_imports,
[<<(oaspec@config:package(oaspec@codegen@context:config(Ctx)))/binary,
"/types"/utf8>>]
);
false ->
Base_imports
end,
Imports = case Needs_option of
true ->
lists:append(Base_imports@1, [<<"gleam/option"/utf8>>]);
false ->
Base_imports@1
end,
Sb = begin
_pipe = oaspec@util@string_extra:file_header(<<"0.18.0"/utf8>>),
oaspec@util@string_extra:imports(_pipe, Imports)
end,
Schemas@1 = case erlang:element(5, oaspec@codegen@context:spec(Ctx)) of
{some, Components@1} ->
_pipe@1 = gleam@list:sort(
maps:to_list(erlang:element(2, Components@1)),
fun(A@1, B@1) ->
gleam@string:compare(
erlang:element(1, A@1),
erlang:element(1, B@1)
)
end
),
gleam@list:filter(
_pipe@1,
fun(Entry@3) ->
not oaspec@codegen@ir_build:is_internal_schema(
erlang:element(2, Entry@3)
)
end
);
none ->
[]
end,
Sb@2 = gleam@list:fold(
Schemas@1,
Sb,
fun(Sb@1, Entry@4) ->
{Name, Schema_ref@3} = Entry@4,
generate_inline_enum_decoders(Sb@1, Name, Schema_ref@3, Ctx)
end
),
Sb@4 = gleam@list:fold(
Schemas@1,
Sb@2,
fun(Sb@3, Entry@5) ->
{Name@1, Schema_ref@4} = Entry@5,
generate_decoder(Sb@3, Name@1, Schema_ref@4, Ctx)
end
),
Sb@5 = generate_anonymous_decoders(Sb@4, Ctx, Operations),
oaspec@util@string_extra:to_string(Sb@5).
-file("src/oaspec/codegen/decoders.gleam", 28).
?DOC(
" Generate the `decode.gleam` module for the resolved spec.\n"
"\n"
" Encoder generation lives in `src/oaspec/codegen/encoders.gleam`; see\n"
" `generate.gleam::generate_shared` for how the two halves are combined.\n"
).
-spec generate(oaspec@codegen@context:context()) -> list(oaspec@codegen@context:generated_file()).
generate(Ctx) ->
Operations = oaspec@openapi@operations:collect_operations(Ctx),
Decode_content = generate_decoders(Ctx, Operations),
[{generated_file,
<<"decode.gleam"/utf8>>,
Decode_content,
shared_target,
overwrite}].