Packages

Emit an OpenAPI 3.1.0 document from atproto lexicons.

Current section

Files

Jump to
atproto_openapi src atproto_openapi@schema.erl
Raw

src/atproto_openapi@schema.erl

-module(atproto_openapi@schema).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/atproto_openapi/schema.gleam").
-export([array_item_type/2, object_schema/2, primary_def/2, property_type/2, params_property_type/2, body_schema/2]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(false).
-file("src/atproto_openapi/schema.gleam", 44).
?DOC(false).
-spec 'maybe'(
binary(),
gleam@option:option(IGM),
fun((IGM) -> gleam@json:json())
) -> list({binary(), gleam@json:json()}).
'maybe'(Key, Value, To_json) ->
case Value of
{some, V} ->
[{Key, To_json(V)}];
none ->
[]
end.
-file("src/atproto_openapi/schema.gleam", 55).
?DOC(false).
-spec non_empty(binary(), list(IGP), fun((IGP) -> gleam@json:json())) -> list({binary(),
gleam@json:json()}).
non_empty(Key, Values, To_json) ->
case Values of
[] ->
[];
_ ->
[{Key, gleam@json:array(Values, To_json)}]
end.
-file("src/atproto_openapi/schema.gleam", 66).
?DOC(false).
-spec kinds(binary(), boolean()) -> list(binary()).
kinds(Base, Nullable) ->
case Nullable of
true ->
[Base, <<"null"/utf8>>];
false ->
[Base]
end.
-file("src/atproto_openapi/schema.gleam", 73).
?DOC(false).
-spec type_field(list(binary())) -> {binary(), gleam@json:json()}.
type_field(Kinds) ->
case Kinds of
[One] ->
{<<"type"/utf8>>, gleam@json:string(One)};
Many ->
{<<"type"/utf8>>, gleam@json:array(Many, fun gleam@json:string/1)}
end.
-file("src/atproto_openapi/schema.gleam", 80).
?DOC(false).
-spec null_schema() -> gleam@json:json().
null_schema() ->
gleam@json:object([{<<"type"/utf8>>, gleam@json:string(<<"null"/utf8>>)}]).
-file("src/atproto_openapi/schema.gleam", 84).
?DOC(false).
-spec combine_description(gleam@option:option(binary()), list(binary())) -> gleam@option:option(binary()).
combine_description(Base, Extra_lines) ->
case {Base, Extra_lines} of
{none, []} ->
none;
{{some, D}, []} ->
{some, D};
{none, Lines} ->
{some, gleam@string:join(Lines, <<"\n"/utf8>>)};
{{some, D@1}, Lines@1} ->
{some, gleam@string:join([D@1 | Lines@1], <<"\n"/utf8>>)}
end.
-file("src/atproto_openapi/schema.gleam", 419).
?DOC(false).
-spec blob_description(
gleam@option:option(binary()),
gleam@option:option(list(binary())),
gleam@option:option(integer())
) -> gleam@option:option(binary()).
blob_description(Description, Accept, Max_size) ->
Accept_line = case Accept of
{some, Types} ->
[<<<<"Accepted MIME types: "/utf8,
(gleam@string:join(Types, <<", "/utf8>>))/binary>>/binary,
"."/utf8>>];
none ->
[]
end,
Max_size_line = case Max_size of
{some, N} ->
[<<<<"Max size: "/utf8, (erlang:integer_to_binary(N))/binary>>/binary,
" bytes."/utf8>>];
none ->
[]
end,
combine_description(Description, lists:append(Accept_line, Max_size_line)).
-file("src/atproto_openapi/schema.gleam", 371).
?DOC(false).
-spec blob_schema(atproto_lexicon@ast:blob_constraints(), boolean()) -> gleam@json:json().
blob_schema(C, Nullable) ->
gleam@json:object(
lists:append(
[[type_field(kinds(<<"object"/utf8>>, Nullable))],
[{<<"properties"/utf8>>,
gleam@json:object(
[{<<"$type"/utf8>>,
gleam@json:object(
[{<<"type"/utf8>>,
gleam@json:string(
<<"string"/utf8>>
)},
{<<"const"/utf8>>,
gleam@json:string(
<<"blob"/utf8>>
)}]
)},
{<<"ref"/utf8>>,
gleam@json:object(
[{<<"type"/utf8>>,
gleam@json:string(
<<"object"/utf8>>
)},
{<<"properties"/utf8>>,
gleam@json:object(
[{<<"$link"/utf8>>,
gleam@json:object(
[{<<"type"/utf8>>,
gleam@json:string(
<<"string"/utf8>>
)}]
)}]
)},
{<<"required"/utf8>>,
gleam@json:array(
[<<"$link"/utf8>>],
fun gleam@json:string/1
)}]
)},
{<<"mimeType"/utf8>>,
gleam@json:object(
[{<<"type"/utf8>>,
gleam@json:string(
<<"string"/utf8>>
)}]
)},
{<<"size"/utf8>>,
gleam@json:object(
[{<<"type"/utf8>>,
gleam@json:string(
<<"integer"/utf8>>
)}]
)}]
)}],
[{<<"required"/utf8>>,
gleam@json:array(
[<<"$type"/utf8>>,
<<"ref"/utf8>>,
<<"mimeType"/utf8>>,
<<"size"/utf8>>],
fun gleam@json:string/1
)}],
'maybe'(
<<"description"/utf8>>,
blob_description(
erlang:element(2, C),
erlang:element(3, C),
erlang:element(4, C)
),
fun gleam@json:string/1
)]
)
).
-file("src/atproto_openapi/schema.gleam", 435).
?DOC(false).
-spec unknown_schema() -> gleam@json:json().
unknown_schema() ->
gleam@json:object([]).
-file("src/atproto_openapi/schema.gleam", 360).
?DOC(false).
-spec cid_link_schema(boolean()) -> gleam@json:json().
cid_link_schema(Nullable) ->
gleam@json:object(
[type_field(kinds(<<"object"/utf8>>, Nullable)),
{<<"properties"/utf8>>,
gleam@json:object(
[{<<"$link"/utf8>>,
gleam@json:object(
[{<<"type"/utf8>>,
gleam@json:string(<<"string"/utf8>>)}]
)}]
)},
{<<"required"/utf8>>,
gleam@json:array([<<"$link"/utf8>>], fun gleam@json:string/1)}]
).
-file("src/atproto_openapi/schema.gleam", 348).
?DOC(false).
-spec bytes_schema(atproto_lexicon@ast:bytes_constraints(), boolean()) -> gleam@json:json().
bytes_schema(C, Nullable) ->
gleam@json:object(
lists:append(
[[type_field(kinds(<<"string"/utf8>>, Nullable))],
[{<<"contentEncoding"/utf8>>,
gleam@json:string(<<"base64"/utf8>>)}],
'maybe'(
<<"maxLength"/utf8>>,
erlang:element(3, C),
fun gleam@json:int/1
),
'maybe'(
<<"minLength"/utf8>>,
erlang:element(4, C),
fun gleam@json:int/1
),
'maybe'(
<<"description"/utf8>>,
erlang:element(2, C),
fun gleam@json:string/1
)]
)
).
-file("src/atproto_openapi/schema.gleam", 274).
?DOC(false).
-spec boolean_schema(atproto_lexicon@ast:boolean_constraints(), boolean()) -> gleam@json:json().
boolean_schema(C, Nullable) ->
gleam@json:object(
lists:append(
[[type_field(kinds(<<"boolean"/utf8>>, Nullable))],
'maybe'(
<<"default"/utf8>>,
erlang:element(3, C),
fun gleam@json:bool/1
),
'maybe'(
<<"const"/utf8>>,
erlang:element(4, C),
fun gleam@json:bool/1
),
'maybe'(
<<"description"/utf8>>,
erlang:element(2, C),
fun gleam@json:string/1
)]
)
).
-file("src/atproto_openapi/schema.gleam", 285).
?DOC(false).
-spec integer_schema(atproto_lexicon@ast:integer_constraints(), boolean()) -> gleam@json:json().
integer_schema(C, Nullable) ->
gleam@json:object(
lists:append(
[[type_field(kinds(<<"integer"/utf8>>, Nullable))],
'maybe'(
<<"minimum"/utf8>>,
erlang:element(3, C),
fun gleam@json:int/1
),
'maybe'(
<<"maximum"/utf8>>,
erlang:element(4, C),
fun gleam@json:int/1
),
'maybe'(
<<"enum"/utf8>>,
erlang:element(5, C),
fun(Vs) -> gleam@json:array(Vs, fun gleam@json:int/1) end
),
'maybe'(
<<"default"/utf8>>,
erlang:element(6, C),
fun gleam@json:int/1
),
'maybe'(
<<"const"/utf8>>,
erlang:element(7, C),
fun gleam@json:int/1
),
'maybe'(
<<"description"/utf8>>,
erlang:element(2, C),
fun gleam@json:string/1
)]
)
).
-file("src/atproto_openapi/schema.gleam", 320).
?DOC(false).
-spec string_description(
gleam@option:option(binary()),
gleam@option:option(list(binary()))
) -> gleam@option:option(binary()).
string_description(Description, Known_values) ->
Extra = case Known_values of
{some, Values} ->
[<<<<"Known values: "/utf8,
(gleam@string:join(Values, <<", "/utf8>>))/binary>>/binary,
"."/utf8>>];
none ->
[]
end,
combine_description(Description, Extra).
-file("src/atproto_openapi/schema.gleam", 331).
?DOC(false).
-spec string_format_json(atproto_lexicon@ast:string_format()) -> gleam@json:json().
string_format_json(Format) ->
gleam@json:string(case Format of
format_datetime ->
<<"date-time"/utf8>>;
format_uri ->
<<"uri"/utf8>>;
format_at_identifier ->
<<"at-identifier"/utf8>>;
format_at_uri ->
<<"at-uri"/utf8>>;
format_cid ->
<<"cid"/utf8>>;
format_did ->
<<"did"/utf8>>;
format_handle ->
<<"handle"/utf8>>;
format_language ->
<<"language"/utf8>>;
format_nsid ->
<<"nsid"/utf8>>;
format_record_key ->
<<"record-key"/utf8>>;
format_tid ->
<<"tid"/utf8>>;
{format_other, Raw} ->
Raw
end).
-file("src/atproto_openapi/schema.gleam", 299).
?DOC(false).
-spec string_schema(atproto_lexicon@ast:string_constraints(), boolean()) -> gleam@json:json().
string_schema(C, Nullable) ->
gleam@json:object(
lists:append(
[[type_field(kinds(<<"string"/utf8>>, Nullable))],
'maybe'(
<<"format"/utf8>>,
erlang:element(3, C),
fun string_format_json/1
),
'maybe'(
<<"maxLength"/utf8>>,
erlang:element(4, C),
fun gleam@json:int/1
),
'maybe'(
<<"minLength"/utf8>>,
erlang:element(5, C),
fun gleam@json:int/1
),
'maybe'(
<<"x-graphemes-max"/utf8>>,
erlang:element(6, C),
fun gleam@json:int/1
),
'maybe'(
<<"x-graphemes-min"/utf8>>,
erlang:element(7, C),
fun gleam@json:int/1
),
'maybe'(
<<"enum"/utf8>>,
erlang:element(9, C),
fun(Vs) -> gleam@json:array(Vs, fun gleam@json:string/1) end
),
'maybe'(
<<"const"/utf8>>,
erlang:element(11, C),
fun gleam@json:string/1
),
'maybe'(
<<"default"/utf8>>,
erlang:element(10, C),
fun gleam@json:string/1
),
'maybe'(
<<"description"/utf8>>,
string_description(
erlang:element(2, C),
erlang:element(8, C)
),
fun gleam@json:string/1
)]
)
).
-file("src/atproto_openapi/schema.gleam", 123).
?DOC(false).
-spec token_schema(atproto_openapi@refs:ref()) -> gleam@json:json().
token_schema(Own) ->
gleam@json:object(
[{<<"type"/utf8>>, gleam@json:string(<<"string"/utf8>>)},
{<<"const"/utf8>>,
gleam@json:string(
<<<<(erlang:element(2, Own))/binary, "#"/utf8>>/binary,
(erlang:element(3, Own))/binary>>
)}]
).
-file("src/atproto_openapi/schema.gleam", 484).
?DOC(false).
-spec union_description(
gleam@option:option(binary()),
gleam@option:option(boolean())
) -> gleam@option:option(binary()).
union_description(Description, Closed) ->
Note = case Closed of
{some, true} ->
<<"Closed union: exactly these members, enforced at write time by the real API."/utf8>>;
_ ->
<<"Open union: readers must tolerate future $type values not listed here."/utf8>>
end,
combine_description(Description, [Note]).
-file("src/atproto_openapi/schema.gleam", 448).
?DOC(false).
-spec union_schema(atproto_lexicon@ast:union_constraints(), binary(), boolean()) -> {ok,
gleam@json:json()} |
{error, atproto_openapi@refs:ref_error()}.
union_schema(C, Doc_id, Nullable) ->
gleam@result:'try'(
gleam@list:try_map(
erlang:element(3, C),
fun(Raw) -> atproto_openapi@refs:schema_pointer(Raw, Doc_id) end
),
fun(Pointers) ->
Ref_members = gleam@list:map(
Pointers,
fun(Pointer) ->
gleam@json:object(
[{<<"$ref"/utf8>>, gleam@json:string(Pointer)}]
)
end
),
Members = case Nullable of
false ->
Ref_members;
true ->
lists:append(Ref_members, [null_schema()])
end,
{ok,
gleam@json:object(
lists:append(
[[{<<"oneOf"/utf8>>,
gleam@json:preprocessed_array(Members)}],
[{<<"discriminator"/utf8>>,
gleam@json:object(
[{<<"propertyName"/utf8>>,
gleam@json:string(
<<"$type"/utf8>>
)}]
)}],
'maybe'(
<<"description"/utf8>>,
union_description(
erlang:element(2, C),
erlang:element(4, C)
),
fun gleam@json:string/1
)]
)
)}
end
).
-file("src/atproto_openapi/schema.gleam", 439).
?DOC(false).
-spec ref_schema(binary(), boolean()) -> gleam@json:json().
ref_schema(Pointer, Nullable) ->
Base = gleam@json:object([{<<"$ref"/utf8>>, gleam@json:string(Pointer)}]),
case Nullable of
false ->
Base;
true ->
gleam@json:object(
[{<<"oneOf"/utf8>>,
gleam@json:preprocessed_array([Base, null_schema()])}]
)
end.
-file("src/atproto_openapi/schema.gleam", 203).
?DOC(false).
-spec array_item_type(atproto_lexicon@ast:array_item_type(), binary()) -> {ok,
gleam@json:json()} |
{error, atproto_openapi@refs:ref_error()}.
array_item_type(It, Doc_id) ->
case It of
{item_boolean, C} ->
{ok, boolean_schema(C, false)};
{item_integer, C@1} ->
{ok, integer_schema(C@1, false)};
{item_string, C@2} ->
{ok, string_schema(C@2, false)};
{item_bytes, C@3} ->
{ok, bytes_schema(C@3, false)};
{item_cid_link, _} ->
{ok, cid_link_schema(false)};
{item_blob, C@4} ->
{ok, blob_schema(C@4, false)};
{item_ref, _, Ref} ->
gleam@result:'try'(
atproto_openapi@refs:schema_pointer(Ref, Doc_id),
fun(Pointer) -> {ok, ref_schema(Pointer, false)} end
);
{item_union, C@5} ->
union_schema(C@5, Doc_id, false);
{item_unknown, _} ->
{ok, unknown_schema()}
end.
-file("src/atproto_openapi/schema.gleam", 499).
?DOC(false).
-spec array_shape_schema(atproto_lexicon@ast:array_shape(), binary(), boolean()) -> {ok,
gleam@json:json()} |
{error, atproto_openapi@refs:ref_error()}.
array_shape_schema(A, Doc_id, Nullable) ->
gleam@result:'try'(
array_item_type(erlang:element(3, A), Doc_id),
fun(Items) ->
{ok,
gleam@json:object(
lists:append(
[[type_field(kinds(<<"array"/utf8>>, Nullable))],
'maybe'(
<<"description"/utf8>>,
erlang:element(2, A),
fun gleam@json:string/1
),
[{<<"items"/utf8>>, Items}],
'maybe'(
<<"minItems"/utf8>>,
erlang:element(4, A),
fun gleam@json:int/1
),
'maybe'(
<<"maxItems"/utf8>>,
erlang:element(5, A),
fun gleam@json:int/1
)]
)
)}
end
).
-file("src/atproto_openapi/schema.gleam", 161).
?DOC(false).
-spec properties_field(list({binary(), gleam@json:json()})) -> list({binary(),
gleam@json:json()}).
properties_field(Properties) ->
case Properties of
[] ->
[];
_ ->
[{<<"properties"/utf8>>, gleam@json:object(Properties)}]
end.
-file("src/atproto_openapi/schema.gleam", 179).
?DOC(false).
-spec property_type_impl(
atproto_lexicon@ast:property_type(),
binary(),
boolean()
) -> {ok, gleam@json:json()} | {error, atproto_openapi@refs:ref_error()}.
property_type_impl(Pt, Doc_id, Nullable) ->
case Pt of
{prop_boolean, C} ->
{ok, boolean_schema(C, Nullable)};
{prop_integer, C@1} ->
{ok, integer_schema(C@1, Nullable)};
{prop_string, C@2} ->
{ok, string_schema(C@2, Nullable)};
{prop_bytes, C@3} ->
{ok, bytes_schema(C@3, Nullable)};
{prop_cid_link, _} ->
{ok, cid_link_schema(Nullable)};
{prop_blob, C@4} ->
{ok, blob_schema(C@4, Nullable)};
{prop_ref, _, Ref} ->
gleam@result:'try'(
atproto_openapi@refs:schema_pointer(Ref, Doc_id),
fun(Pointer) -> {ok, ref_schema(Pointer, Nullable)} end
);
{prop_union, C@5} ->
union_schema(C@5, Doc_id, Nullable);
{prop_unknown, _} ->
{ok, unknown_schema()};
{prop_array, A} ->
array_shape_schema(A, Doc_id, Nullable)
end.
-file("src/atproto_openapi/schema.gleam", 137).
?DOC(false).
-spec object_schema(atproto_lexicon@ast:object_schema(), binary()) -> {ok,
gleam@json:json()} |
{error, atproto_openapi@refs:ref_error()}.
object_schema(O, Doc_id) ->
gleam@result:'try'(
gleam@list:try_map(
erlang:element(5, O),
fun(Entry) ->
{Name, Pt} = Entry,
Nullable = gleam@list:contains(erlang:element(4, O), Name),
gleam@result:'try'(
property_type_impl(Pt, Doc_id, Nullable),
fun(Field) -> {ok, {Name, Field}} end
)
end
),
fun(Properties) ->
{ok,
gleam@json:object(
lists:append(
[[{<<"type"/utf8>>,
gleam@json:string(<<"object"/utf8>>)}],
'maybe'(
<<"description"/utf8>>,
erlang:element(2, O),
fun gleam@json:string/1
),
non_empty(
<<"required"/utf8>>,
erlang:element(3, O),
fun gleam@json:string/1
),
properties_field(Properties)]
)
)}
end
).
-file("src/atproto_openapi/schema.gleam", 104).
?DOC(false).
-spec primary_def(atproto_lexicon@ast:primary_def(), atproto_openapi@refs:ref()) -> {ok,
gleam@json:json()} |
{error, atproto_openapi@refs:ref_error()}.
primary_def(Def, Own) ->
case Def of
{def_record, Rd} ->
object_schema(erlang:element(4, Rd), erlang:element(2, Own));
{def_query, _} ->
{ok, gleam@json:object([])};
{def_procedure, _} ->
{ok, gleam@json:object([])};
{def_subscription, _} ->
{ok, gleam@json:object([])};
{def_object, O} ->
object_schema(O, erlang:element(2, Own));
{def_array, A} ->
array_shape_schema(A, erlang:element(2, Own), false);
{def_token, _} ->
{ok, token_schema(Own)};
{def_string, C} ->
{ok, string_schema(C, false)};
{def_integer, C@1} ->
{ok, integer_schema(C@1, false)};
{def_boolean, C@2} ->
{ok, boolean_schema(C@2, false)};
{def_bytes, C@3} ->
{ok, bytes_schema(C@3, false)};
{def_cid_link, _} ->
{ok, cid_link_schema(false)};
{def_unknown, _} ->
{ok, unknown_schema()};
{def_blob, C@4} ->
{ok, blob_schema(C@4, false)}
end.
-file("src/atproto_openapi/schema.gleam", 172).
?DOC(false).
-spec property_type(atproto_lexicon@ast:property_type(), binary()) -> {ok,
gleam@json:json()} |
{error, atproto_openapi@refs:ref_error()}.
property_type(Pt, Doc_id) ->
property_type_impl(Pt, Doc_id, false).
-file("src/atproto_openapi/schema.gleam", 250).
?DOC(false).
-spec params_item_type(atproto_lexicon@ast:params_item_type()) -> gleam@json:json().
params_item_type(It) ->
case It of
{params_item_boolean, C} ->
boolean_schema(C, false);
{params_item_integer, C@1} ->
integer_schema(C@1, false);
{params_item_string, C@2} ->
string_schema(C@2, false)
end.
-file("src/atproto_openapi/schema.gleam", 225).
?DOC(false).
-spec params_property_type(atproto_lexicon@ast:params_property_type(), binary()) -> {ok,
gleam@json:json()} |
{error, atproto_openapi@refs:ref_error()}.
params_property_type(Pt, _) ->
case Pt of
{params_boolean, C} ->
{ok, boolean_schema(C, false)};
{params_integer, C@1} ->
{ok, integer_schema(C@1, false)};
{params_string, C@2} ->
{ok, string_schema(C@2, false)};
{params_unknown, _} ->
{ok, unknown_schema()};
{params_array, Description, Items, Min_length, Max_length} ->
{ok,
gleam@json:object(
lists:append(
[[{<<"type"/utf8>>, gleam@json:string(<<"array"/utf8>>)}],
'maybe'(
<<"description"/utf8>>,
Description,
fun gleam@json:string/1
),
[{<<"items"/utf8>>, params_item_type(Items)}],
'maybe'(
<<"minItems"/utf8>>,
Min_length,
fun gleam@json:int/1
),
'maybe'(
<<"maxItems"/utf8>>,
Max_length,
fun gleam@json:int/1
)]
)
)}
end.
-file("src/atproto_openapi/schema.gleam", 261).
?DOC(false).
-spec body_schema(atproto_lexicon@ast:body_schema(), binary()) -> {ok,
gleam@json:json()} |
{error, atproto_openapi@refs:ref_error()}.
body_schema(Bs, Doc_id) ->
case Bs of
{body_schema_object, O} ->
object_schema(O, Doc_id);
{body_schema_ref, Ref} ->
gleam@result:'try'(
atproto_openapi@refs:schema_pointer(Ref, Doc_id),
fun(Pointer) -> {ok, ref_schema(Pointer, false)} end
);
{body_schema_union, C} ->
union_schema(C, Doc_id, false)
end.