Packages
oaspec
0.22.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@codegen@ir_build.erl
-module(oaspec@codegen@ir_build).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/oaspec/codegen/ir_build.gleam").
-export([sorted_entries/1, build_request_types_module/1, build_response_types_module/1, is_internal_schema/1, build_types_module/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/ir_build.gleam", 84).
-spec compute_request_type_imports(
list({binary(),
oaspec@openapi@spec:operation(oaspec@openapi@spec:resolved()),
binary(),
oaspec@openapi@spec:http_method()}),
oaspec@codegen@context:context()
) -> list(binary()).
compute_request_type_imports(Operations, Ctx) ->
Needs_option = oaspec@codegen@import_analysis:operations_have_optional_params(
Operations
)
orelse oaspec@codegen@import_analysis:operations_have_optional_body(
Operations
),
Needs_types = oaspec@codegen@import_analysis:operations_need_typed_schemas(
Operations
),
Base_imports = case Needs_types of
true ->
[<<(oaspec@config:package(oaspec@codegen@context:config(Ctx)))/binary,
"/types"/utf8>>];
false ->
[]
end,
case Needs_option of
true ->
[<<"gleam/option.{type Option}"/utf8>> | Base_imports];
false ->
Base_imports
end.
-file("src/oaspec/codegen/ir_build.gleam", 140).
-spec request_param_field(
oaspec@openapi@spec:parameter(oaspec@openapi@spec:resolved()),
binary()
) -> oaspec@codegen@ir:field().
request_param_field(Param, Field_name) ->
Field_type = case erlang:element(6, Param) of
{parameter_schema, {inline, {string_schema, _, _, _, _, _, _}}} ->
<<"String"/utf8>>;
{parameter_schema, {inline, {integer_schema, _, _, _, _, _, _, _}}} ->
<<"Int"/utf8>>;
{parameter_schema, {inline, {number_schema, _, _, _, _, _, _, _}}} ->
<<"Float"/utf8>>;
{parameter_schema, {inline, {boolean_schema, _}}} ->
<<"Bool"/utf8>>;
{parameter_schema, {inline, {array_schema, _, Items, _, _, _}}} ->
Item_type = case Items of
{inline, {string_schema, _, _, _, _, _, _}} ->
<<"String"/utf8>>;
{inline, {integer_schema, _, _, _, _, _, _, _}} ->
<<"Int"/utf8>>;
{inline, {number_schema, _, _, _, _, _, _, _}} ->
<<"Float"/utf8>>;
{inline, {boolean_schema, _}} ->
<<"Bool"/utf8>>;
{reference, _, Name} ->
oaspec@util@naming:schema_to_type_name(Name);
_ ->
<<"String"/utf8>>
end,
<<<<"List("/utf8, Item_type/binary>>/binary, ")"/utf8>>;
{parameter_schema, {reference, _, Name@1}} ->
<<"types."/utf8,
(oaspec@util@naming:schema_to_type_name(Name@1))/binary>>;
_ ->
<<"String"/utf8>>
end,
Final_type = case erlang:element(5, Param) of
true ->
Field_type;
false ->
<<<<"Option("/utf8, Field_type/binary>>/binary, ")"/utf8>>
end,
{field, Field_name, Final_type}.
-file("src/oaspec/codegen/ir_build.gleam", 279).
?DOC(" Convert a header schema to a Gleam type string.\n").
-spec header_schema_to_type(
gleam@option:option(oaspec@openapi@schema:schema_ref())
) -> binary().
header_schema_to_type(Schema_opt) ->
case Schema_opt of
{some, {inline, {integer_schema, _, _, _, _, _, _, _}}} ->
<<"Int"/utf8>>;
{some, {inline, {number_schema, _, _, _, _, _, _, _}}} ->
<<"Float"/utf8>>;
{some, {inline, {boolean_schema, _}}} ->
<<"Bool"/utf8>>;
{some, {inline, {string_schema, _, _, _, _, _, _}}} ->
<<"String"/utf8>>;
_ ->
<<"String"/utf8>>
end.
-file("src/oaspec/codegen/ir_build.gleam", 290).
?DOC(" Check if any response header record has optional fields.\n").
-spec response_headers_need_option(
list(oaspec@codegen@ir:response_header_record())
) -> boolean().
response_headers_need_option(Records) ->
gleam@list:any(
Records,
fun(Rec) ->
gleam@list:any(
erlang:element(3, Rec),
fun(F) ->
gleam_stdlib:string_starts_with(
erlang:element(3, F),
<<"Option("/utf8>>
)
end
)
end
).
-file("src/oaspec/codegen/ir_build.gleam", 296).
-spec responses_need_types_import(
list({binary(),
oaspec@openapi@spec:operation(oaspec@openapi@spec:resolved()),
binary(),
oaspec@openapi@spec:http_method()})
) -> boolean().
responses_need_types_import(Operations) ->
gleam@list:any(
Operations,
fun(Op) ->
{_, Operation, _, _} = Op,
Responses = maps:to_list(erlang:element(8, Operation)),
gleam@list:any(
Responses,
fun(Entry) ->
{_, Ref_or} = Entry,
case Ref_or of
{value, Response} ->
Content_entries = maps:to_list(
erlang:element(3, Response)
),
case Content_entries of
[] ->
false;
[_, _ | _] ->
false;
[{Media_type_name, Media_type}] ->
case oaspec@util@content_type:from_string(
Media_type_name
) of
text_plain ->
false;
application_xml ->
false;
text_xml ->
false;
application_octet_stream ->
false;
_ ->
case erlang:element(2, Media_type) of
{some, {reference, _, _}} ->
true;
{some,
{inline,
{array_schema,
_,
{reference, _, _},
_,
_,
_}}} ->
true;
{some,
{inline,
{object_schema,
_,
_,
_,
_,
_,
_}}} ->
true;
{some,
{inline,
{one_of_schema, _, _, _}}} ->
true;
{some,
{inline,
{any_of_schema, _, _, _}}} ->
true;
{some,
{inline,
{all_of_schema, _, _}}} ->
true;
_ ->
false
end
end
end;
_ ->
false
end
end
)
end
).
-file("src/oaspec/codegen/ir_build.gleam", 407).
-spec schema_to_gleam_type_qualified(
oaspec@openapi@schema:schema_object(),
binary(),
binary()
) -> binary().
schema_to_gleam_type_qualified(Schema_obj, Op_id, Suffix) ->
case Schema_obj of
{array_schema, _, Items, _, _, _} ->
case Items of
{reference, _, Name} ->
<<<<"List(types."/utf8,
(oaspec@util@naming:schema_to_type_name(Name))/binary>>/binary,
")"/utf8>>;
_ ->
oaspec@codegen@schema_dispatch:schema_type(Schema_obj)
end;
{object_schema, _, _, _, _, _, _} ->
Type_name = <<(oaspec@util@naming:schema_to_type_name(Op_id))/binary,
Suffix/binary>>,
<<"types."/utf8, Type_name/binary>>;
{one_of_schema, _, Schemas, _} ->
All_refs = gleam@list:all(Schemas, fun(S) -> case S of
{reference, _, _} ->
true;
_ ->
false
end end),
case All_refs of
true ->
Type_name@1 = <<(oaspec@util@naming:schema_to_type_name(
Op_id
))/binary,
Suffix/binary>>,
<<"types."/utf8, Type_name@1/binary>>;
false ->
oaspec@codegen@schema_dispatch:schema_type(Schema_obj)
end;
{any_of_schema, _, Schemas@1, _} ->
All_refs@1 = gleam@list:all(Schemas@1, fun(S@1) -> case S@1 of
{reference, _, _} ->
true;
_ ->
false
end end),
case All_refs@1 of
true ->
Type_name@2 = <<(oaspec@util@naming:schema_to_type_name(
Op_id
))/binary,
Suffix/binary>>,
<<"types."/utf8, Type_name@2/binary>>;
false ->
oaspec@codegen@schema_dispatch:schema_type(Schema_obj)
end;
{all_of_schema, _, _} ->
Type_name@3 = <<(oaspec@util@naming:schema_to_type_name(Op_id))/binary,
Suffix/binary>>,
<<"types."/utf8, Type_name@3/binary>>;
_ ->
oaspec@codegen@schema_dispatch:schema_type(Schema_obj)
end.
-file("src/oaspec/codegen/ir_build.gleam", 395).
-spec schema_ref_to_type_qualified(
oaspec@openapi@schema:schema_ref(),
binary(),
binary()
) -> binary().
schema_ref_to_type_qualified(Ref, Op_id, Suffix) ->
case Ref of
{inline, Schema_obj} ->
schema_to_gleam_type_qualified(Schema_obj, Op_id, Suffix);
{reference, _, Name} ->
<<"types."/utf8,
(oaspec@util@naming:schema_to_type_name(Name))/binary>>
end.
-file("src/oaspec/codegen/ir_build.gleam", 463).
-spec inline_request_body_type(oaspec@openapi@schema:schema_object(), binary()) -> binary().
inline_request_body_type(Schema_obj, Op_id) ->
case Schema_obj of
{object_schema, _, _, _, _, _, _} ->
Type_name = <<(oaspec@util@naming:schema_to_type_name(Op_id))/binary,
"RequestBody"/utf8>>,
<<"types."/utf8, Type_name/binary>>;
{all_of_schema, _, _} ->
Type_name@1 = <<(oaspec@util@naming:schema_to_type_name(Op_id))/binary,
"RequestBody"/utf8>>,
<<"types."/utf8, Type_name@1/binary>>;
{string_schema, _, _, _, _, _, _} ->
<<"String"/utf8>>;
{integer_schema, _, _, _, _, _, _, _} ->
<<"Int"/utf8>>;
{number_schema, _, _, _, _, _, _, _} ->
<<"Float"/utf8>>;
{boolean_schema, _} ->
<<"Bool"/utf8>>;
_ ->
oaspec@codegen@schema_dispatch:schema_type(Schema_obj)
end.
-file("src/oaspec/codegen/ir_build.gleam", 485).
-spec compute_imports(
list({binary(), oaspec@openapi@schema:schema_ref()}),
oaspec@codegen@context:context()
) -> list(binary()).
compute_imports(Schemas, Ctx) ->
Needs_option = gleam@list:any(
Schemas,
fun(Entry) ->
{_, Schema_ref} = Entry,
case Schema_ref of
{inline, {any_of_schema, _, _, _}} ->
true;
_ ->
oaspec@codegen@schema_utils:schema_has_optional_fields(
Schema_ref,
Ctx
)
end
end
),
Needs_dict = gleam@list:any(
Schemas,
fun(Entry@1) ->
{_, Schema_ref@1} = Entry@1,
oaspec@codegen@schema_utils:schema_has_additional_properties(
Schema_ref@1,
Ctx
)
end
),
Needs_dynamic = gleam@list:any(
Schemas,
fun(Entry@2) ->
{_, Schema_ref@2} = Entry@2,
oaspec@codegen@schema_utils:schema_has_untyped_additional_properties(
Schema_ref@2,
Ctx
)
end
),
case {Needs_option, Needs_dict, Needs_dynamic} of
{true, true, true} ->
[<<"gleam/dict.{type Dict}"/utf8>>,
<<"gleam/dynamic.{type Dynamic}"/utf8>>,
<<"gleam/option.{type Option}"/utf8>>];
{true, true, false} ->
[<<"gleam/dict.{type Dict}"/utf8>>,
<<"gleam/option.{type Option}"/utf8>>];
{true, false, _} ->
[<<"gleam/option.{type Option}"/utf8>>];
{false, true, true} ->
[<<"gleam/dict.{type Dict}"/utf8>>,
<<"gleam/dynamic.{type Dynamic}"/utf8>>];
{false, true, false} ->
[<<"gleam/dict.{type Dict}"/utf8>>];
{false, false, _} ->
[]
end.
-file("src/oaspec/codegen/ir_build.gleam", 901).
-spec schema_ref_to_type(
oaspec@openapi@schema:schema_ref(),
oaspec@codegen@context:context()
) -> binary().
schema_ref_to_type(Ref, _) ->
case Ref of
{inline, S} ->
oaspec@codegen@schema_dispatch:schema_type(S);
{reference, _, Name} ->
oaspec@util@naming:schema_to_type_name(Name)
end.
-file("src/oaspec/codegen/ir_build.gleam", 886).
-spec schema_ref_to_type_with_inline_enum(
oaspec@openapi@schema:schema_ref(),
binary(),
binary(),
oaspec@codegen@context:context()
) -> binary().
schema_ref_to_type_with_inline_enum(Ref, Parent_name, Prop_name, Ctx) ->
case Ref of
{inline, {string_schema, _, _, Enum_values, _, _, _}} when Enum_values =/= [] ->
<<(oaspec@util@naming:schema_to_type_name(Parent_name))/binary,
(oaspec@util@naming:schema_to_type_name(Prop_name))/binary>>;
_ ->
schema_ref_to_type(Ref, Ctx)
end.
-file("src/oaspec/codegen/ir_build.gleam", 911).
?DOC(
" Sort dict entries by key for deterministic output ordering.\n"
" Gleam Dict does not guarantee iteration order, so all codegen paths\n"
" that produce output from dict entries must sort first.\n"
).
-spec sorted_entries(gleam@dict:dict(binary(), ITC)) -> list({binary(), ITC}).
sorted_entries(D) ->
_pipe = maps:to_list(D),
gleam@list:sort(
_pipe,
fun(A, B) ->
gleam@string:compare(erlang:element(1, A), erlang:element(1, B))
end
).
-file("src/oaspec/codegen/ir_build.gleam", 184).
-spec request_body_type(
oaspec@openapi@spec:request_body(oaspec@openapi@spec:resolved()),
binary(),
oaspec@codegen@context:context()
) -> binary().
request_body_type(Rb, Op_id, _) ->
Content_entries = sorted_entries(erlang:element(3, Rb)),
case Content_entries of
[{_, Media_type} | _] ->
case erlang:element(2, Media_type) of
{some, {reference, _, Name}} ->
<<"types."/utf8,
(oaspec@util@naming:schema_to_type_name(Name))/binary>>;
{some, {inline, Schema_obj}} ->
inline_request_body_type(Schema_obj, Op_id);
_ ->
<<"String"/utf8>>
end;
[] ->
<<"String"/utf8>>
end.
-file("src/oaspec/codegen/ir_build.gleam", 171).
-spec request_body_field(
oaspec@openapi@spec:request_body(oaspec@openapi@spec:resolved()),
binary(),
oaspec@codegen@context:context()
) -> oaspec@codegen@ir:field().
request_body_field(Rb, Op_id, Ctx) ->
Body_type = request_body_type(Rb, Op_id, Ctx),
Final_type = case erlang:element(4, Rb) of
true ->
Body_type;
false ->
<<<<"Option("/utf8, Body_type/binary>>/binary, ")"/utf8>>
end,
{field, <<"body"/utf8>>, Final_type}.
-file("src/oaspec/codegen/ir_build.gleam", 102).
-spec request_type_decl(
binary(),
oaspec@openapi@spec:operation(oaspec@openapi@spec:resolved()),
oaspec@codegen@context:context()
) -> {ok, oaspec@codegen@ir:declaration()} | {error, nil}.
request_type_decl(Op_id, Operation, Ctx) ->
Params = erlang:element(6, Operation),
case gleam@list:is_empty(Params) andalso gleam@option:is_none(
erlang:element(7, Operation)
) of
true ->
{error, nil};
false ->
Type_name = <<(oaspec@util@naming:schema_to_type_name(Op_id))/binary,
"Request"/utf8>>,
Resolved_params = gleam@list:filter_map(
Params,
fun(Ref_p) -> case Ref_p of
{value, Param} ->
{ok, Param};
_ ->
{error, nil}
end end
),
Deduped_names = oaspec@openapi@dedup:dedup_param_field_names(
Resolved_params
),
Param_fields = gleam@list:map(
gleam@list:zip(Resolved_params, Deduped_names),
fun(Pair) ->
{Param@1, Field_name} = Pair,
request_param_field(Param@1, Field_name)
end
),
Body_field = case erlang:element(7, Operation) of
{some, {value, Rb}} ->
[request_body_field(Rb, Op_id, Ctx)];
_ ->
[]
end,
{ok,
oaspec@codegen@ir:declaration(
erlang:element(4, Operation),
{record_type,
Type_name,
lists:append(Param_fields, Body_field)}
)}
end.
-file("src/oaspec/codegen/ir_build.gleam", 73).
?DOC(
" Build an IR Module for the request_types.gleam file from operations.\n"
" Each operation with at least one parameter or a request body yields a\n"
" single `RecordType` declaration. Operations with neither parameters nor\n"
" body produce no declaration — matching the former string-builder\n"
" behavior that simply skipped them.\n"
).
-spec build_request_types_module(oaspec@codegen@context:context()) -> oaspec@codegen@ir:module_().
build_request_types_module(Ctx) ->
Operations = oaspec@openapi@operations:collect_operations(Ctx),
Imports = compute_request_type_imports(Operations, Ctx),
Declarations = gleam@list:filter_map(
Operations,
fun(Op) ->
{Op_id, Operation, _, _} = Op,
request_type_decl(Op_id, Operation, Ctx)
end
),
oaspec@codegen@ir:module(<<""/utf8>>, Imports, Declarations).
-file("src/oaspec/codegen/ir_build.gleam", 239).
?DOC(" Build ResponseHeaderRecord list from all operations.\n").
-spec build_response_header_records(
list({binary(),
oaspec@openapi@spec:operation(oaspec@openapi@spec:resolved()),
binary(),
oaspec@openapi@spec:http_method()})
) -> list(oaspec@codegen@ir:response_header_record()).
build_response_header_records(Operations) ->
gleam@list:flat_map(
Operations,
fun(Op) ->
{Op_id, Operation, _, _} = Op,
Type_name = <<(oaspec@util@naming:schema_to_type_name(Op_id))/binary,
"Response"/utf8>>,
Responses = oaspec@util@http:sort_response_entries(
maps:to_list(erlang:element(8, Operation))
),
gleam@list:filter_map(
Responses,
fun(Entry) ->
{Status_code, Ref_or} = Entry,
case Ref_or of
{value, Response} ->
Headers = sorted_entries(
erlang:element(4, Response)
),
case Headers of
[] ->
{error, nil};
_ ->
Record_name = <<<<Type_name/binary,
(oaspec@util@http:status_code_suffix(
Status_code
))/binary>>/binary,
"Headers"/utf8>>,
Fields = gleam@list:map(
Headers,
fun(H_entry) ->
{Header_name, Header} = H_entry,
Field_name = oaspec@util@naming:to_snake_case(
Header_name
),
Field_type = header_schema_to_type(
erlang:element(4, Header)
),
Final_type = case erlang:element(
3,
Header
) of
true ->
Field_type;
false ->
<<<<"Option("/utf8,
Field_type/binary>>/binary,
")"/utf8>>
end,
{field, Field_name, Final_type}
end
),
{ok,
{response_header_record,
Record_name,
Fields}}
end;
_ ->
{error, nil}
end
end
)
end
).
-file("src/oaspec/codegen/ir_build.gleam", 361).
-spec response_variant(
binary(),
binary(),
oaspec@util@http:http_status_code(),
oaspec@openapi@spec:response(oaspec@openapi@spec:resolved())
) -> oaspec@codegen@ir:variant().
response_variant(Type_name, Op_id, Status_code, Response) ->
Variant_name = <<Type_name/binary,
(oaspec@util@http:status_code_suffix(Status_code))/binary>>,
Content_entries = sorted_entries(erlang:element(3, Response)),
case Content_entries of
[] ->
{variant_empty, Variant_name};
[_, _ | _] ->
{variant_with_type, Variant_name, <<"String"/utf8>>};
[{Media_type_name, Media_type}] ->
case oaspec@util@content_type:from_string(Media_type_name) of
text_plain ->
case erlang:element(2, Media_type) of
{some, _} ->
{variant_with_type, Variant_name, <<"String"/utf8>>};
none ->
{variant_empty, Variant_name}
end;
application_xml ->
case erlang:element(2, Media_type) of
{some, _} ->
{variant_with_type, Variant_name, <<"String"/utf8>>};
none ->
{variant_empty, Variant_name}
end;
text_xml ->
case erlang:element(2, Media_type) of
{some, _} ->
{variant_with_type, Variant_name, <<"String"/utf8>>};
none ->
{variant_empty, Variant_name}
end;
application_octet_stream ->
case erlang:element(2, Media_type) of
{some, _} ->
{variant_with_type, Variant_name, <<"String"/utf8>>};
none ->
{variant_empty, Variant_name}
end;
_ ->
case erlang:element(2, Media_type) of
{some, Ref} ->
Suffix = <<"Response"/utf8,
(oaspec@util@http:status_code_suffix(
Status_code
))/binary>>,
Inner_type = schema_ref_to_type_qualified(
Ref,
Op_id,
Suffix
),
{variant_with_type, Variant_name, Inner_type};
none ->
{variant_empty, Variant_name}
end
end
end.
-file("src/oaspec/codegen/ir_build.gleam", 335).
-spec response_type_decl(
binary(),
oaspec@openapi@spec:operation(oaspec@openapi@spec:resolved())
) -> {ok, oaspec@codegen@ir:declaration()} | {error, nil}.
response_type_decl(Op_id, Operation) ->
Type_name = <<(oaspec@util@naming:schema_to_type_name(Op_id))/binary,
"Response"/utf8>>,
Responses = oaspec@util@http:sort_response_entries(
maps:to_list(erlang:element(8, Operation))
),
case Responses of
[] ->
{error, nil};
_ ->
Variants = gleam@list:filter_map(
Responses,
fun(Entry) ->
{Status_code, Ref_or} = Entry,
case Ref_or of
{value, Response} ->
{ok,
response_variant(
Type_name,
Op_id,
Status_code,
Response
)};
_ ->
{error, nil}
end
end
),
{ok,
oaspec@codegen@ir:declaration(
none,
{union_type, Type_name, Variants}
)}
end.
-file("src/oaspec/codegen/ir_build.gleam", 209).
?DOC(
" Build an IR Module for the response_types.gleam file from operations.\n"
" Each operation with at least one response yields a `UnionType`\n"
" declaration whose variants correspond to HTTP status codes. Variant\n"
" payloads follow the same rules the former string-builder applied:\n"
" empty responses become `VariantEmpty`; text/XML/octet-stream bodies\n"
" become `VariantWithType(\"String\")`; JSON (and other structured) bodies\n"
" become `VariantWithType(<qualified schema type>)`.\n"
).
-spec build_response_types_module(oaspec@codegen@context:context()) -> oaspec@codegen@ir:module_().
build_response_types_module(Ctx) ->
Operations = oaspec@openapi@operations:collect_operations(Ctx),
Header_records = build_response_header_records(Operations),
Needs_option_for_headers = response_headers_need_option(Header_records),
Imports = case {responses_need_types_import(Operations),
Needs_option_for_headers} of
{true, true} ->
[<<"gleam/option.{type Option}"/utf8>>,
<<(oaspec@config:package(oaspec@codegen@context:config(Ctx)))/binary,
"/types"/utf8>>];
{true, false} ->
[<<(oaspec@config:package(oaspec@codegen@context:config(Ctx)))/binary,
"/types"/utf8>>];
{false, true} ->
[<<"gleam/option.{type Option}"/utf8>>];
{false, false} ->
[]
end,
Declarations = gleam@list:filter_map(
Operations,
fun(Op) ->
{Op_id, Operation, _, _} = Op,
response_type_decl(Op_id, Operation)
end
),
oaspec@codegen@ir:module_with_header_records(
<<""/utf8>>,
Imports,
Declarations,
Header_records
).
-file("src/oaspec/codegen/ir_build.gleam", 550).
-spec inline_enums_from_properties(
binary(),
gleam@dict:dict(binary(), oaspec@openapi@schema:schema_ref()),
oaspec@codegen@context:context()
) -> list(oaspec@codegen@ir:declaration()).
inline_enums_from_properties(Parent_name, Properties, _) ->
Entries = sorted_entries(Properties),
gleam@list:filter_map(
Entries,
fun(Entry) ->
{Prop_name, Prop_ref} = Entry,
case Prop_ref of
{inline, {string_schema, Metadata, _, Enum_values, _, _, _}} when Enum_values =/= [] ->
Type_name = <<(oaspec@util@naming:schema_to_type_name(
Parent_name
))/binary,
(oaspec@util@naming:schema_to_type_name(Prop_name))/binary>>,
Deduped_variants = oaspec@openapi@dedup:dedup_enum_variants(
Enum_values
),
Variants = begin
_pipe = gleam@list:zip(Enum_values, Deduped_variants),
gleam@list:map(
_pipe,
fun(Pair) ->
{_, Variant_suffix} = Pair,
<<(oaspec@util@naming:schema_to_type_name(
Type_name
))/binary,
Variant_suffix/binary>>
end
)
end,
{ok,
oaspec@codegen@ir:declaration(
erlang:element(2, Metadata),
{enum_type, Type_name, Variants}
)};
_ ->
{error, nil}
end
end
).
-file("src/oaspec/codegen/ir_build.gleam", 534).
-spec inline_enums_for_schema(
binary(),
oaspec@openapi@schema:schema_ref(),
oaspec@codegen@context:context()
) -> list(oaspec@codegen@ir:declaration()).
inline_enums_for_schema(Parent_name, Schema_ref, Ctx) ->
case Schema_ref of
{inline, {object_schema, _, Properties, _, _, _, _}} ->
inline_enums_from_properties(Parent_name, Properties, Ctx);
{inline, {all_of_schema, _, Schemas}} ->
Merged = oaspec@codegen@allof_merge:merge_allof_schemas(
Schemas,
Ctx
),
inline_enums_from_properties(
Parent_name,
erlang:element(2, Merged),
Ctx
);
_ ->
[]
end.
-file("src/oaspec/codegen/ir_build.gleam", 604).
-spec schema_type_decls(
binary(),
binary(),
oaspec@openapi@schema:schema_object(),
oaspec@codegen@context:context()
) -> list(oaspec@codegen@ir:declaration()).
schema_type_decls(Type_name, Raw_name, Schema, Ctx) ->
case Schema of
{object_schema,
Metadata,
Properties,
Required,
Additional_properties,
_,
_} ->
Props = sorted_entries(Properties),
Deduped_names = oaspec@openapi@dedup:dedup_property_names(
gleam@list:map(Props, fun(E) -> erlang:element(1, E) end)
),
Fields = begin
_pipe = gleam@list:zip(Props, Deduped_names),
gleam@list:map(
_pipe,
fun(Pair) ->
{Entry, Field_name} = Pair,
{Prop_name, Prop_ref} = Entry,
Field_type = schema_ref_to_type_with_inline_enum(
Prop_ref,
Raw_name,
Prop_name,
Ctx
),
Is_required = gleam@list:contains(Required, Prop_name),
Is_already_optional = oaspec@codegen@schema_utils:schema_ref_is_nullable(
Prop_ref,
Ctx
),
Final_type = case {Is_required, Is_already_optional} of
{true, _} ->
Field_type;
{false, true} ->
Field_type;
{false, false} ->
<<<<"Option("/utf8, Field_type/binary>>/binary,
")"/utf8>>
end,
{field, Field_name, Final_type}
end
)
end,
Fields@1 = case Additional_properties of
{typed, Ap_ref} ->
Inner_type = schema_ref_to_type(Ap_ref, Ctx),
lists:append(
Fields,
[{field,
<<"additional_properties"/utf8>>,
<<<<"Dict(String, "/utf8, Inner_type/binary>>/binary,
")"/utf8>>}]
);
untyped ->
lists:append(
Fields,
[{field,
<<"additional_properties"/utf8>>,
<<"Dict(String, Dynamic)"/utf8>>}]
);
forbidden ->
Fields;
unspecified ->
Fields
end,
[oaspec@codegen@ir:declaration(
erlang:element(2, Metadata),
{record_type, Type_name, Fields@1}
)];
{string_schema, Metadata@1, _, Enum_values, _, _, _} when Enum_values =/= [] ->
Deduped_variants = oaspec@openapi@dedup:dedup_enum_variants(
Enum_values
),
Variants = begin
_pipe@1 = gleam@list:zip(Enum_values, Deduped_variants),
gleam@list:map(
_pipe@1,
fun(Pair@1) ->
{_, Variant_suffix} = Pair@1,
<<(oaspec@util@naming:schema_to_type_name(Type_name))/binary,
Variant_suffix/binary>>
end
)
end,
[oaspec@codegen@ir:declaration(
erlang:element(2, Metadata@1),
{enum_type, Type_name, Variants}
)];
{one_of_schema, Metadata@2, Schemas, _} ->
Variants@1 = gleam@list:map(
Schemas,
fun(S_ref) ->
Variant_type = schema_ref_to_type(S_ref, Ctx),
Variant_name = <<Type_name/binary, Variant_type/binary>>,
{variant_with_type, Variant_name, Variant_type}
end
),
[oaspec@codegen@ir:declaration(
erlang:element(2, Metadata@2),
{union_type, Type_name, Variants@1}
)];
{any_of_schema, Metadata@3, Schemas@1, _} ->
Fields@2 = gleam@list:map(
Schemas@1,
fun(S_ref@1) ->
Variant_type@1 = schema_ref_to_type(S_ref@1, Ctx),
Field_name@1 = oaspec@util@naming:to_snake_case(
Variant_type@1
),
{field,
Field_name@1,
<<<<"Option("/utf8, Variant_type@1/binary>>/binary,
")"/utf8>>}
end
),
[oaspec@codegen@ir:declaration(
erlang:element(2, Metadata@3),
{record_type, Type_name, Fields@2}
)];
{all_of_schema, Metadata@4, Schemas@2} ->
Merged = oaspec@codegen@allof_merge:merge_allof_schemas(
Schemas@2,
Ctx
),
Merged_schema = {object_schema,
Metadata@4,
erlang:element(2, Merged),
erlang:element(3, Merged),
erlang:element(4, Merged),
none,
none},
schema_type_decls(Type_name, Raw_name, Merged_schema, Ctx);
_ ->
Gleam_type = oaspec@codegen@schema_dispatch:schema_type(Schema),
[oaspec@codegen@ir:declaration(
none,
{type_alias, Type_name, Gleam_type}
)]
end.
-file("src/oaspec/codegen/ir_build.gleam", 584).
-spec type_def_decls(
binary(),
oaspec@openapi@schema:schema_ref(),
oaspec@codegen@context:context()
) -> list(oaspec@codegen@ir:declaration()).
type_def_decls(Name, Schema_ref, Ctx) ->
Type_name = oaspec@util@naming:schema_to_type_name(Name),
case Schema_ref of
{inline, Schema} ->
schema_type_decls(Type_name, Name, Schema, Ctx);
{reference, _, Ref_name} ->
Resolved_type = oaspec@util@naming:schema_to_type_name(Ref_name),
[oaspec@codegen@ir:declaration(
none,
{type_alias, Type_name, Resolved_type}
)]
end.
-file("src/oaspec/codegen/ir_build.gleam", 827).
-spec anonymous_type_for_schema(
binary(),
binary(),
oaspec@openapi@schema:schema_object(),
oaspec@codegen@context:context()
) -> list(oaspec@codegen@ir:declaration()).
anonymous_type_for_schema(Op_id, Suffix, Schema_obj, Ctx) ->
Type_name = <<(oaspec@util@naming:schema_to_type_name(Op_id))/binary,
Suffix/binary>>,
Raw_name = <<<<Op_id/binary, "_"/utf8>>/binary, Suffix/binary>>,
case Schema_obj of
{object_schema, _, _, _, _, _, _} ->
schema_type_decls(Type_name, Raw_name, Schema_obj, Ctx);
{one_of_schema, _, Schemas, _} ->
All_refs = gleam@list:all(Schemas, fun(S) -> case S of
{reference, _, _} ->
true;
_ ->
false
end end),
case All_refs of
true ->
Variants = gleam@list:map(
Schemas,
fun(S_ref) ->
Variant_type = schema_ref_to_type(S_ref, Ctx),
Variant_name = <<Type_name/binary,
Variant_type/binary>>,
{variant_with_type, Variant_name, Variant_type}
end
),
[oaspec@codegen@ir:declaration(
none,
{union_type, Type_name, Variants}
)];
false ->
[]
end;
{any_of_schema, _, _, _} ->
schema_type_decls(Type_name, Raw_name, Schema_obj, Ctx);
{all_of_schema, Metadata, Schemas@1} ->
Merged = oaspec@codegen@allof_merge:merge_allof_schemas(
Schemas@1,
Ctx
),
Merged_schema = {object_schema,
Metadata,
erlang:element(2, Merged),
erlang:element(3, Merged),
erlang:element(4, Merged),
none,
none},
schema_type_decls(Type_name, Raw_name, Merged_schema, Ctx);
_ ->
[]
end.
-file("src/oaspec/codegen/ir_build.gleam", 763).
-spec anonymous_response_type_decls(
binary(),
oaspec@openapi@spec:operation(oaspec@openapi@spec:resolved()),
oaspec@codegen@context:context()
) -> list(oaspec@codegen@ir:declaration()).
anonymous_response_type_decls(Op_id, Operation, Ctx) ->
Responses = oaspec@util@http:sort_response_entries(
maps:to_list(erlang:element(8, Operation))
),
gleam@list:flat_map(
Responses,
fun(Entry) ->
{Status_code, Ref_or} = Entry,
case Ref_or of
{value, Response} ->
Content_entries = 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@schema_utils:filter_write_only_properties(
Schema_obj,
Ctx
),
anonymous_type_for_schema(
Op_id,
<<"Response"/utf8,
(oaspec@util@http:status_code_suffix(
Status_code
))/binary>>,
Filtered_schema,
Ctx
);
_ ->
[]
end;
_ ->
[]
end;
_ ->
[]
end
end
).
-file("src/oaspec/codegen/ir_build.gleam", 797).
-spec anonymous_request_body_type_decls(
binary(),
oaspec@openapi@spec:operation(oaspec@openapi@spec:resolved()),
oaspec@codegen@context:context()
) -> list(oaspec@codegen@ir:declaration()).
anonymous_request_body_type_decls(Op_id, Operation, Ctx) ->
case erlang:element(7, Operation) of
{some, {value, Rb}} ->
Content_entries = 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@schema_utils:filter_read_only_properties(
Schema_obj,
Ctx
),
anonymous_type_for_schema(
Op_id,
<<"RequestBody"/utf8>>,
Filtered_schema,
Ctx
);
_ ->
[]
end;
_ ->
[]
end;
_ ->
[]
end.
-file("src/oaspec/codegen/ir_build.gleam", 748).
-spec anonymous_type_decls(oaspec@codegen@context:context()) -> list(oaspec@codegen@ir:declaration()).
anonymous_type_decls(Ctx) ->
Operations = oaspec@openapi@operations:collect_operations(Ctx),
gleam@list:flat_map(
Operations,
fun(Op) ->
{Op_id, Operation, _, _} = Op,
Response_decls = anonymous_response_type_decls(
Op_id,
Operation,
Ctx
),
Request_decls = anonymous_request_body_type_decls(
Op_id,
Operation,
Ctx
),
lists:append(Response_decls, Request_decls)
end
).
-file("src/oaspec/codegen/ir_build.gleam", 916).
?DOC(" Check if a schema ref is marked as internal (allOf helper type).\n").
-spec is_internal_schema(oaspec@openapi@schema:schema_ref()) -> boolean().
is_internal_schema(Schema_ref) ->
case Schema_ref of
{inline, Obj} ->
erlang:element(13, oaspec@openapi@schema:get_metadata(Obj));
_ ->
false
end.
-file("src/oaspec/codegen/ir_build.gleam", 32).
?DOC(" Build an IR Module for the types.gleam file from component schemas.\n").
-spec build_types_module(oaspec@codegen@context:context()) -> oaspec@codegen@ir:module_().
build_types_module(Ctx) ->
Schemas = case erlang:element(5, oaspec@codegen@context:spec(Ctx)) of
{some, Components} ->
_pipe = 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
),
gleam@list:filter(
_pipe,
fun(Entry) ->
not is_internal_schema(erlang:element(2, Entry))
end
);
none ->
[]
end,
Imports = compute_imports(Schemas, Ctx),
Inline_enum_decls = gleam@list:flat_map(
Schemas,
fun(Entry@1) ->
{Name, Schema_ref} = Entry@1,
inline_enums_for_schema(Name, Schema_ref, Ctx)
end
),
Main_decls = gleam@list:flat_map(
Schemas,
fun(Entry@2) ->
{Name@1, Schema_ref@1} = Entry@2,
type_def_decls(Name@1, Schema_ref@1, Ctx)
end
),
Anon_decls = anonymous_type_decls(Ctx),
oaspec@codegen@ir:module(
<<""/utf8>>,
Imports,
lists:append([Inline_enum_decls, Main_decls, Anon_decls])
).