Packages

Code First GraphQL library for Gleam

Current section

Files

Jump to
mochi src mochi@schema_printer.erl
Raw

src/mochi@schema_printer.erl

-module(mochi@schema_printer).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/mochi/schema_printer.gleam").
-export([print_type_definition/1, print_schema/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/mochi/schema_printer.gleam", 237).
?DOC(" Print field type (handles NonNull, List, Named)\n").
-spec print_field_type(mochi@schema:field_type()) -> binary().
print_field_type(Field_type) ->
case Field_type of
{named, Name} ->
Name;
{non_null, Inner} ->
<<(print_field_type(Inner))/binary, "!"/utf8>>;
{list, Inner@1} ->
<<<<"["/utf8, (print_field_type(Inner@1))/binary>>/binary,
"]"/utf8>>
end.
-file("src/mochi/schema_printer.gleam", 246).
?DOC(" Print schema definition if it has custom root types\n").
-spec print_schema_definition(mochi@schema:schema()) -> binary().
print_schema_definition(Schema_def) ->
Parts = [],
Parts@1 = case erlang:element(2, Schema_def) of
{some, Query} when erlang:element(2, Query) =/= <<"Query"/utf8>> ->
[<<"query: "/utf8, (erlang:element(2, Query))/binary>> | Parts];
_ ->
Parts
end,
Parts@2 = case erlang:element(3, Schema_def) of
{some, Mutation} when erlang:element(2, Mutation) =/= <<"Mutation"/utf8>> ->
[<<"mutation: "/utf8, (erlang:element(2, Mutation))/binary>> |
Parts@1];
_ ->
Parts@1
end,
Parts@3 = case erlang:element(4, Schema_def) of
{some, Subscription} when erlang:element(2, Subscription) =/= <<"Subscription"/utf8>> ->
[<<"subscription: "/utf8, (erlang:element(2, Subscription))/binary>> |
Parts@2];
_ ->
Parts@2
end,
case Parts@3 of
[] ->
<<""/utf8>>;
_ ->
<<<<"schema {\n "/utf8,
(gleam@string:join(lists:reverse(Parts@3), <<"\n "/utf8>>))/binary>>/binary,
"\n}"/utf8>>
end.
-file("src/mochi/schema_printer.gleam", 277).
?DOC(" Check if schema has custom root type names\n").
-spec has_custom_root_types(mochi@schema:schema()) -> boolean().
has_custom_root_types(Schema_def) ->
Query_custom = case erlang:element(2, Schema_def) of
{some, Query} ->
erlang:element(2, Query) /= <<"Query"/utf8>>;
none ->
false
end,
Mutation_custom = case erlang:element(3, Schema_def) of
{some, Mutation} ->
erlang:element(2, Mutation) /= <<"Mutation"/utf8>>;
none ->
false
end,
Subscription_custom = case erlang:element(4, Schema_def) of
{some, Subscription} ->
erlang:element(2, Subscription) /= <<"Subscription"/utf8>>;
none ->
false
end,
(Query_custom orelse Mutation_custom) orelse Subscription_custom.
-file("src/mochi/schema_printer.gleam", 297).
?DOC(" Print description as a comment\n").
-spec print_description(binary()) -> binary().
print_description(Desc) ->
<<<<"\"\"\""/utf8, Desc/binary>>/binary, "\"\"\""/utf8>>.
-file("src/mochi/schema_printer.gleam", 78).
?DOC(" Print scalar type: scalar DateTime\n").
-spec print_scalar_type(mochi@schema:scalar_type()) -> binary().
print_scalar_type(Scalar) ->
Result = <<"scalar "/utf8, (erlang:element(2, Scalar))/binary>>,
case erlang:element(3, Scalar) of
{some, Desc} ->
<<<<(print_description(Desc))/binary, "\n"/utf8>>/binary,
Result/binary>>;
none ->
Result
end.
-file("src/mochi/schema_printer.gleam", 127).
?DOC(" Print union type: union SearchResult = User | Post\n").
-spec print_union_type(mochi@schema:union_type()) -> binary().
print_union_type(Union) ->
Header = <<"union "/utf8, (erlang:element(2, Union))/binary>>,
Header@1 = case erlang:element(3, Union) of
{some, Desc} ->
<<<<(print_description(Desc))/binary, "\n"/utf8>>/binary,
Header/binary>>;
none ->
Header
end,
Members = begin
_pipe = gleam@list:map(
erlang:element(4, Union),
fun(T) -> erlang:element(2, T) end
),
gleam@string:join(_pipe, <<" | "/utf8>>)
end,
case Members of
<<""/utf8>> ->
Header@1;
_ ->
<<<<Header@1/binary, " = "/utf8>>/binary, Members/binary>>
end.
-file("src/mochi/schema_printer.gleam", 302).
?DOC(" Print description inline\n").
-spec print_description_inline(binary()) -> binary().
print_description_inline(Desc) ->
<<"# "/utf8, Desc/binary>>.
-file("src/mochi/schema_printer.gleam", 224).
?DOC(" Print enum value\n").
-spec print_enum_value(mochi@schema:enum_value_definition(), binary()) -> binary().
print_enum_value(Enum_value, Indent) ->
Base = <<Indent/binary, (erlang:element(2, Enum_value))/binary>>,
case erlang:element(3, Enum_value) of
{some, Desc} ->
<<<<(print_description_inline(Desc))/binary, "\n"/utf8>>/binary,
Base/binary>>;
none ->
Base
end.
-file("src/mochi/schema_printer.gleam", 87).
?DOC(" Print enum type: enum Status { ACTIVE INACTIVE }\n").
-spec print_enum_type(mochi@schema:enum_type()) -> binary().
print_enum_type(Enum) ->
Header = <<"enum "/utf8, (erlang:element(2, Enum))/binary>>,
Header@1 = case erlang:element(3, Enum) of
{some, Desc} ->
<<<<(print_description(Desc))/binary, "\n"/utf8>>/binary,
Header/binary>>;
none ->
Header
end,
Values = begin
_pipe = maps:to_list(erlang:element(4, Enum)),
_pipe@1 = gleam@list:map(
_pipe,
fun(Entry) ->
print_enum_value(erlang:element(2, Entry), <<" "/utf8>>)
end
),
gleam@string:join(_pipe@1, <<"\n"/utf8>>)
end,
case Values of
<<""/utf8>> ->
Header@1;
_ ->
<<<<<<Header@1/binary, " {\n"/utf8>>/binary, Values/binary>>/binary,
"\n}"/utf8>>
end.
-file("src/mochi/schema_printer.gleam", 343).
?DOC(" Escape special characters in a string for SDL\n").
-spec escape_string(binary()) -> binary().
escape_string(S) ->
_pipe = S,
_pipe@1 = gleam@string:replace(_pipe, <<"\\"/utf8>>, <<"\\\\"/utf8>>),
_pipe@2 = gleam@string:replace(_pipe@1, <<"\""/utf8>>, <<"\\\""/utf8>>),
_pipe@3 = gleam@string:replace(_pipe@2, <<"\n"/utf8>>, <<"\\n"/utf8>>),
_pipe@4 = gleam@string:replace(_pipe@3, <<"\r"/utf8>>, <<"\\r"/utf8>>),
gleam@string:replace(_pipe@4, <<"\t"/utf8>>, <<"\\t"/utf8>>).
-file("src/mochi/schema_printer.gleam", 322).
-spec print_typed_value(mochi@output:value()) -> binary().
print_typed_value(V) ->
case V of
{v_string, S} ->
<<<<"\""/utf8, (escape_string(S))/binary>>/binary, "\""/utf8>>;
{v_int, I} ->
erlang:integer_to_binary(I);
{v_float, F} ->
gleam_stdlib:float_to_string(F);
{v_bool, true} ->
<<"true"/utf8>>;
{v_bool, false} ->
<<"false"/utf8>>;
v_null ->
<<"null"/utf8>>;
{v_list, Items} ->
<<<<"["/utf8,
(gleam@string:join(
gleam@list:map(Items, fun print_typed_value/1),
<<", "/utf8>>
))/binary>>/binary,
"]"/utf8>>;
{v_object, Fields} ->
<<<<"{ "/utf8,
(gleam@string:join(
gleam@list:map(
Fields,
fun(Kv) ->
<<<<(erlang:element(1, Kv))/binary, ": "/utf8>>/binary,
(print_typed_value(erlang:element(2, Kv)))/binary>>
end
),
<<", "/utf8>>
))/binary>>/binary,
" }"/utf8>>
end.
-file("src/mochi/schema_printer.gleam", 315).
?DOC(
" Print a Dynamic value in GraphQL SDL format. Uses a single\n"
" classification pass via `output.from_dynamic` instead of a cascade of\n"
" decoders, and walks the typed value tree to produce SDL.\n"
"\n"
" Unrepresentable runtime shapes degrade to `null` rather than panicking\n"
" (SDL printing is best-effort here — it's only used for default-value\n"
" rendering, where the worst case is a slightly less informative\n"
" schema dump). The proper fix is to type the default-value field at\n"
" the schema level, which is on the migration list in AGENTS.md.\n"
).
-spec print_value(gleam@dynamic:dynamic_()) -> binary().
print_value(Value) ->
case mochi@output:from_dynamic(Value) of
{ok, V} ->
print_typed_value(V);
{error, _} ->
<<"null"/utf8>>
end.
-file("src/mochi/schema_printer.gleam", 195).
?DOC(" Print input field definition\n").
-spec print_input_field_definition(
mochi@schema:input_field_definition(),
binary()
) -> binary().
print_input_field_definition(Field, Indent) ->
Base = <<<<<<Indent/binary, (erlang:element(2, Field))/binary>>/binary,
": "/utf8>>/binary,
(print_field_type(erlang:element(4, Field)))/binary>>,
Base@1 = case erlang:element(5, Field) of
{some, Value} ->
<<<<Base/binary, " = "/utf8>>/binary, (print_value(Value))/binary>>;
none ->
Base
end,
case erlang:element(3, Field) of
{some, Desc} ->
<<<<(print_description_inline(Desc))/binary, "\n"/utf8>>/binary,
Base@1/binary>>;
none ->
Base@1
end.
-file("src/mochi/schema_printer.gleam", 146).
?DOC(" Print input object type: input CreateUserInput { ... }\n").
-spec print_input_object_type(mochi@schema:input_object_type()) -> binary().
print_input_object_type(Input) ->
Header = <<"input "/utf8, (erlang:element(2, Input))/binary>>,
Header@1 = case erlang:element(3, Input) of
{some, Desc} ->
<<<<(print_description(Desc))/binary, "\n"/utf8>>/binary,
Header/binary>>;
none ->
Header
end,
Fields = begin
_pipe = maps:to_list(erlang:element(4, Input)),
_pipe@1 = gleam@list:map(
_pipe,
fun(Entry) ->
print_input_field_definition(
erlang:element(2, Entry),
<<" "/utf8>>
)
end
),
gleam@string:join(_pipe@1, <<"\n"/utf8>>)
end,
case Fields of
<<""/utf8>> ->
Header@1;
_ ->
<<<<<<Header@1/binary, " {\n"/utf8>>/binary, Fields/binary>>/binary,
"\n}"/utf8>>
end.
-file("src/mochi/schema_printer.gleam", 214).
?DOC(" Print argument definition\n").
-spec print_argument_definition(mochi@schema:argument_definition()) -> binary().
print_argument_definition(Arg) ->
Base = <<<<(erlang:element(2, Arg))/binary, ": "/utf8>>/binary,
(print_field_type(erlang:element(4, Arg)))/binary>>,
case erlang:element(5, Arg) of
{some, Value} ->
<<<<Base/binary, " = "/utf8>>/binary, (print_value(Value))/binary>>;
none ->
Base
end.
-file("src/mochi/schema_printer.gleam", 166).
?DOC(" Print field definition within a type\n").
-spec print_field_definition(mochi@schema:field_definition(), binary()) -> binary().
print_field_definition(Field, Indent) ->
Base = <<Indent/binary, (erlang:element(2, Field))/binary>>,
Base@1 = case maps:size(erlang:element(5, Field)) of
0 ->
Base;
_ ->
Args = begin
_pipe = maps:to_list(erlang:element(5, Field)),
_pipe@1 = gleam@list:map(
_pipe,
fun(Entry) ->
print_argument_definition(erlang:element(2, Entry))
end
),
gleam@string:join(_pipe@1, <<", "/utf8>>)
end,
<<<<<<Base/binary, "("/utf8>>/binary, Args/binary>>/binary,
")"/utf8>>
end,
Base@2 = <<<<Base@1/binary, ": "/utf8>>/binary,
(print_field_type(erlang:element(4, Field)))/binary>>,
case erlang:element(3, Field) of
{some, Desc} ->
<<<<(print_description_inline(Desc))/binary, "\n"/utf8>>/binary,
Base@2/binary>>;
none ->
Base@2
end.
-file("src/mochi/schema_printer.gleam", 50).
?DOC(" Print object type: type User { ... }\n").
-spec print_object_type(mochi@schema:object_type()) -> binary().
print_object_type(Obj) ->
Header = <<"type "/utf8, (erlang:element(2, Obj))/binary>>,
Header@1 = case erlang:element(3, Obj) of
{some, Desc} ->
<<<<(print_description(Desc))/binary, "\n"/utf8>>/binary,
Header/binary>>;
none ->
Header
end,
Header@2 = case erlang:length(erlang:element(5, Obj)) of
0 ->
Header@1;
_ ->
<<<<Header@1/binary, " implements "/utf8>>/binary,
(gleam@string:join(
gleam@list:map(
erlang:element(5, Obj),
fun(I) -> erlang:element(2, I) end
),
<<" & "/utf8>>
))/binary>>
end,
Fields = begin
_pipe = maps:to_list(erlang:element(4, Obj)),
_pipe@1 = gleam@list:map(
_pipe,
fun(Entry) ->
print_field_definition(erlang:element(2, Entry), <<" "/utf8>>)
end
),
gleam@string:join(_pipe@1, <<"\n"/utf8>>)
end,
case Fields of
<<""/utf8>> ->
Header@2;
_ ->
<<<<<<Header@2/binary, " {\n"/utf8>>/binary, Fields/binary>>/binary,
"\n}"/utf8>>
end.
-file("src/mochi/schema_printer.gleam", 107).
?DOC(" Print interface type: interface Node { ... }\n").
-spec print_interface_type(mochi@schema:interface_type()) -> binary().
print_interface_type(Interface) ->
Header = <<"interface "/utf8, (erlang:element(2, Interface))/binary>>,
Header@1 = case erlang:element(3, Interface) of
{some, Desc} ->
<<<<(print_description(Desc))/binary, "\n"/utf8>>/binary,
Header/binary>>;
none ->
Header
end,
Fields = begin
_pipe = maps:to_list(erlang:element(4, Interface)),
_pipe@1 = gleam@list:map(
_pipe,
fun(Entry) ->
print_field_definition(erlang:element(2, Entry), <<" "/utf8>>)
end
),
gleam@string:join(_pipe@1, <<"\n"/utf8>>)
end,
case Fields of
<<""/utf8>> ->
Header@1;
_ ->
<<<<<<Header@1/binary, " {\n"/utf8>>/binary, Fields/binary>>/binary,
"\n}"/utf8>>
end.
-file("src/mochi/schema_printer.gleam", 38).
?DOC(" Print individual type definition\n").
-spec print_type_definition(mochi@schema:type_definition()) -> binary().
print_type_definition(Type_def) ->
case Type_def of
{object_type_def, Obj} ->
print_object_type(Obj);
{scalar_type_def, Scalar} ->
print_scalar_type(Scalar);
{enum_type_def, Enum} ->
print_enum_type(Enum);
{interface_type_def, Interface} ->
print_interface_type(Interface);
{union_type_def, Union} ->
print_union_type(Union);
{input_object_type_def, Input} ->
print_input_object_type(Input)
end.
-file("src/mochi/schema_printer.gleam", 17).
?DOC(" Print a schema to SDL format\n").
-spec print_schema(mochi@schema:schema()) -> binary().
print_schema(Schema_def) ->
Parts = [],
Parts@1 = case has_custom_root_types(Schema_def) of
true ->
[print_schema_definition(Schema_def) | Parts];
false ->
Parts
end,
Type_parts = begin
_pipe = maps:to_list(erlang:element(5, Schema_def)),
_pipe@1 = gleam@list:map(
_pipe,
fun(Entry) -> print_type_definition(erlang:element(2, Entry)) end
),
gleam@list:filter(_pipe@1, fun(S) -> S /= <<""/utf8>> end)
end,
All_parts = lists:append(Parts@1, Type_parts),
gleam@string:join(All_parts, <<"\n\n"/utf8>>).