Packages

Gleam library for building Model Context Protocol servers and transports

Current section

Files

Jump to
mcp_toolkit src mcp_toolkit@core@json_schema.erl
Raw

src/mcp_toolkit@core@json_schema.erl

-module(mcp_toolkit@core@json_schema).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/mcp_toolkit/core/json_schema.gleam").
-export([codegen/0, root_name/2, generate_encoders/2, generate_decoders/2, generate/2, decoder/1, decode_object_schema/1, object_schema_to_json/1, to_json/1]).
-export_type([root_schema/0, type/0, schema/0, object_schema/0, generator/0, out/0, codegen_error/0, property_data_name/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" <https://json-schema.org/>\n"
"\n"
" <https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-00>\n"
).
-type root_schema() :: {root_schema, list({binary(), schema()}), schema()}.
-type type() :: boolean |
string |
number |
integer |
array_type |
object_type |
null.
-type schema() :: {empty, list({binary(), gleam@dynamic:dynamic_()})} |
{type, boolean(), list({binary(), gleam@dynamic:dynamic_()}), type()} |
{enum,
boolean(),
list({binary(), gleam@dynamic:dynamic_()}),
list(binary())} |
{object,
boolean(),
list({binary(), gleam@dynamic:dynamic_()}),
object_schema()} |
{array, boolean(), list({binary(), gleam@dynamic:dynamic_()}), schema()} |
{ref, boolean(), list({binary(), gleam@dynamic:dynamic_()}), binary()} |
{one_of,
boolean(),
list({binary(), gleam@dynamic:dynamic_()}),
list(schema())} |
{all_of,
boolean(),
list({binary(), gleam@dynamic:dynamic_()}),
list(schema())} |
{any_of,
boolean(),
list({binary(), gleam@dynamic:dynamic_()}),
list(schema())} |
{'not', boolean(), list({binary(), gleam@dynamic:dynamic_()}), schema()}.
-type object_schema() :: {object_schema,
list({binary(), schema()}),
list(binary()),
gleam@option:option(schema()),
list({binary(), schema()})}.
-opaque generator() :: {generator,
boolean(),
boolean(),
boolean(),
boolean(),
boolean(),
boolean(),
gleam@dict:dict(binary(), binary()),
gleam@dict:dict(binary(), binary()),
binary(),
gleam@set:set(binary())}.
-type out() :: {out, binary(), binary()}.
-type codegen_error() :: cannot_convert_empty_to_json_error |
empty_enum_error |
{duplicate_property_error, binary(), binary(), binary()} |
{duplicate_constructor_error, binary()} |
{duplicate_type_error, binary()} |
{duplicate_function_error, binary()}.
-type property_data_name() :: property_data_none |
property_data_direct |
{property_data_access, binary()}.
-file("src/mcp_toolkit/core/json_schema.gleam", 219).
-spec type_to_json(type()) -> gleam@json:json().
type_to_json(T) ->
gleam@json:string(case T of
boolean ->
<<"boolean"/utf8>>;
string ->
<<"string"/utf8>>;
number ->
<<"number"/utf8>>;
integer ->
<<"integer"/utf8>>;
array_type ->
<<"array"/utf8>>;
object_type ->
<<"object"/utf8>>;
null ->
<<"null"/utf8>>
end).
-file("src/mcp_toolkit/core/json_schema.gleam", 294).
-spec key_decoder(
gleam@dict:dict(binary(), gleam@dynamic:dynamic_()),
binary(),
fun((gleam@dynamic:dynamic_(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_())) -> {ok,
VHA} |
{error, list(gleam@dynamic@decode:decode_error())})
) -> {ok,
fun(() -> {ok, VHA} | {error, list(gleam@dynamic@decode:decode_error())})} |
{error, nil}.
key_decoder(Data, Key, Constructor) ->
case gleam_stdlib:map_get(Data, Key) of
{ok, Value} ->
{ok, fun() -> Constructor(Value, Data) end};
{error, E} ->
{error, E}
end.
-file("src/mcp_toolkit/core/json_schema.gleam", 528).
-spec get_metadata(gleam@dict:dict(binary(), gleam@dynamic:dynamic_())) -> {ok,
list({binary(), gleam@dynamic:dynamic_()})} |
{error, list(gleam@dynamic@decode:decode_error())}.
get_metadata(Data) ->
Ignored_keys = gleam@set:from_list(
[<<"type"/utf8>>,
<<"enum"/utf8>>,
<<"$ref"/utf8>>,
<<"items"/utf8>>,
<<"properties"/utf8>>,
<<"required"/utf8>>,
<<"additionalProperties"/utf8>>,
<<"patternProperties"/utf8>>,
<<"oneOf"/utf8>>,
<<"anyOf"/utf8>>,
<<"allOf"/utf8>>,
<<"not"/utf8>>,
<<"$defs"/utf8>>,
<<"definitions"/utf8>>,
<<"nullable"/utf8>>]
),
Extract_metadata = fun(Acc, Key, Value) ->
case gleam@set:contains(Ignored_keys, Key) of
true ->
Acc;
false ->
[{Key, Value} | Acc]
end
end,
Metadata = gleam@dict:fold(Data, [], Extract_metadata),
{ok, Metadata}.
-file("src/mcp_toolkit/core/json_schema.gleam", 515).
-spec decode_empty(gleam@dict:dict(binary(), gleam@dynamic:dynamic_())) -> {ok,
schema()} |
{error, list(gleam@dynamic@decode:decode_error())}.
decode_empty(Data) ->
gleam@result:'try'(
get_metadata(Data),
fun(Metadata) -> {ok, {empty, Metadata}} end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 549).
-spec get_nullable(gleam@dict:dict(binary(), gleam@dynamic:dynamic_())) -> {ok,
boolean()} |
{error, list(gleam@dynamic@decode:decode_error())}.
get_nullable(Data) ->
case gleam_stdlib:map_get(Data, <<"nullable"/utf8>>) of
{ok, Data@1} ->
gleam@dynamic@decode:run(
Data@1,
{decoder, fun gleam@dynamic@decode:decode_bool/1}
);
{error, _} ->
case gleam_stdlib:map_get(Data, <<"type"/utf8>>) of
{ok, Type_value} ->
case gleam@dynamic@decode:run(
Type_value,
gleam@dynamic@decode:list(
{decoder, fun gleam@dynamic@decode:decode_string/1}
)
) of
{ok, Types} ->
{ok, gleam@list:contains(Types, <<"null"/utf8>>)};
{error, _} ->
{ok, false}
end;
{error, _} ->
{ok, false}
end
end.
-file("src/mcp_toolkit/core/json_schema.gleam", 463).
-spec decode_type(
gleam@dynamic:dynamic_(),
gleam@dict:dict(binary(), gleam@dynamic:dynamic_())
) -> {ok, schema()} | {error, list(gleam@dynamic@decode:decode_error())}.
decode_type(Type_, Data) ->
gleam@result:'try'(
begin
_pipe = gleam@dynamic@decode:run(
Type_,
{decoder, fun gleam@dynamic@decode:decode_string/1}
),
gleam@result:lazy_or(
_pipe,
fun() ->
_pipe@1 = gleam@dynamic@decode:run(
Type_,
gleam@dynamic@decode:list(
{decoder, fun gleam@dynamic@decode:decode_string/1}
)
),
gleam@result:map(_pipe@1, fun(Types) -> case Types of
[T] ->
T;
_ ->
<<"object"/utf8>>
end end)
end
)
end,
fun(Type_@1) ->
gleam@result:'try'(
get_nullable(Data),
fun(Nullable) ->
gleam@result:'try'(
get_metadata(Data),
fun(Metadata) -> case Type_@1 of
<<"boolean"/utf8>> ->
{ok, {type, Nullable, Metadata, boolean}};
<<"string"/utf8>> ->
{ok, {type, Nullable, Metadata, string}};
<<"number"/utf8>> ->
{ok, {type, Nullable, Metadata, number}};
<<"integer"/utf8>> ->
{ok, {type, Nullable, Metadata, integer}};
<<"array"/utf8>> ->
{ok, {type, Nullable, Metadata, array_type}};
<<"object"/utf8>> ->
{ok,
{type, Nullable, Metadata, object_type}};
<<"null"/utf8>> ->
{ok, {type, Nullable, Metadata, null}};
_ ->
{ok,
{type, Nullable, Metadata, object_type}}
end end
)
end
)
end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 495).
-spec decode_enum(
gleam@dynamic:dynamic_(),
gleam@dict:dict(binary(), gleam@dynamic:dynamic_())
) -> {ok, schema()} | {error, list(gleam@dynamic@decode:decode_error())}.
decode_enum(Variants, Data) ->
gleam@result:'try'(
get_nullable(Data),
fun(Nullable) ->
gleam@result:'try'(
get_metadata(Data),
fun(Metadata) ->
_pipe = gleam@dynamic@decode:run(
Variants,
gleam@dynamic@decode:list(
{decoder, fun gleam@dynamic@decode:decode_string/1}
)
),
gleam@result:map(
_pipe,
fun(_capture) ->
{enum, Nullable, Metadata, _capture}
end
)
end
)
end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 505).
-spec decode_ref(
gleam@dynamic:dynamic_(),
gleam@dict:dict(binary(), gleam@dynamic:dynamic_())
) -> {ok, schema()} | {error, list(gleam@dynamic@decode:decode_error())}.
decode_ref(Ref, Data) ->
gleam@result:'try'(
get_nullable(Data),
fun(Nullable) ->
gleam@result:'try'(
get_metadata(Data),
fun(Metadata) ->
_pipe = gleam@dynamic@decode:run(
Ref,
{decoder, fun gleam@dynamic@decode:decode_string/1}
),
gleam@result:map(
_pipe,
fun(_capture) -> {ref, Nullable, Metadata, _capture} end
)
end
)
end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 570).
-spec metadata_value_to_json(gleam@dynamic:dynamic_()) -> gleam@json:json().
metadata_value_to_json(Data) ->
Decoder = gleam@dynamic@decode:one_of(
gleam@dynamic@decode:map(
{decoder, fun gleam@dynamic@decode:decode_string/1},
fun gleam@json:string/1
),
[gleam@dynamic@decode:map(
{decoder, fun gleam@dynamic@decode:decode_int/1},
fun gleam@json:int/1
),
gleam@dynamic@decode:map(
{decoder, fun gleam@dynamic@decode:decode_float/1},
fun gleam@json:float/1
),
gleam@dynamic@decode:map(
{decoder, fun gleam@dynamic@decode:decode_bool/1},
fun gleam@json:bool/1
)]
),
case gleam@dynamic@decode:run(Data, Decoder) of
{ok, Data@1} ->
Data@1;
{error, _} ->
gleam@json:string(gleam@string:inspect(Data))
end.
-file("src/mcp_toolkit/core/json_schema.gleam", 583).
-spec add_metadata(
list({binary(), gleam@json:json()}),
list({binary(), gleam@dynamic:dynamic_()})
) -> list({binary(), gleam@json:json()}).
add_metadata(Data, Metadata) ->
gleam@list:fold(
Metadata,
Data,
fun(Acc, Meta) ->
[{erlang:element(1, Meta),
metadata_value_to_json(erlang:element(2, Meta))} |
Acc]
end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 592).
-spec add_nullable(list({binary(), gleam@json:json()}), boolean()) -> list({binary(),
gleam@json:json()}).
add_nullable(Data, Nullable) ->
case Nullable of
false ->
Data;
true ->
[{<<"nullable"/utf8>>, gleam@json:bool(true)} | Data]
end.
-file("src/mcp_toolkit/core/json_schema.gleam", 617).
-spec codegen() -> generator().
codegen() ->
{generator,
false,
false,
false,
false,
false,
false,
maps:new(),
maps:new(),
<<"Data"/utf8>>,
gleam@set:new()}.
-file("src/mcp_toolkit/core/json_schema.gleam", 632).
-spec root_name(generator(), binary()) -> generator().
root_name(Gen, Root_name) ->
{generator,
erlang:element(2, Gen),
erlang:element(3, Gen),
erlang:element(4, Gen),
erlang:element(5, Gen),
erlang:element(6, Gen),
erlang:element(7, Gen),
erlang:element(8, Gen),
erlang:element(9, Gen),
Root_name,
erlang:element(11, Gen)}.
-file("src/mcp_toolkit/core/json_schema.gleam", 636).
-spec generate_encoders(generator(), boolean()) -> generator().
generate_encoders(Gen, X) ->
{generator,
erlang:element(2, Gen),
X,
erlang:element(4, Gen),
erlang:element(5, Gen),
erlang:element(6, Gen),
erlang:element(7, Gen),
erlang:element(8, Gen),
erlang:element(9, Gen),
erlang:element(10, Gen),
erlang:element(11, Gen)}.
-file("src/mcp_toolkit/core/json_schema.gleam", 640).
-spec generate_decoders(generator(), boolean()) -> generator().
generate_decoders(Gen, X) ->
{generator,
X,
erlang:element(3, Gen),
erlang:element(4, Gen),
erlang:element(5, Gen),
erlang:element(6, Gen),
erlang:element(7, Gen),
erlang:element(8, Gen),
erlang:element(9, Gen),
erlang:element(10, Gen),
erlang:element(11, Gen)}.
-file("src/mcp_toolkit/core/json_schema.gleam", 763).
-spec type_name(schema(), binary()) -> binary().
type_name(Schema, Name) ->
Nullable@1 = case Schema of
{empty, _} ->
false;
{'not', Nullable, _, _} ->
Nullable;
{array, Nullable, _, _} ->
Nullable;
{enum, Nullable, _, _} ->
Nullable;
{one_of, Nullable, _, _} ->
Nullable;
{any_of, Nullable, _, _} ->
Nullable;
{all_of, Nullable, _, _} ->
Nullable;
{object, Nullable, _, _} ->
Nullable;
{ref, Nullable, _, _} ->
Nullable;
{type, Nullable, _, _} ->
Nullable
end,
Name@1 = case Schema of
{enum, _, _, _} ->
Name;
{object, _, _, _} ->
Name;
{ref, _, _, Ref} ->
case gleam@string:split(Ref, <<"/"/utf8>>) of
[<<"#"/utf8>>, <<"definitions"/utf8>>, Def_name] ->
justin:pascal_case(Def_name);
[<<"#"/utf8>>, <<"$defs"/utf8>>, Def_name@1] ->
justin:pascal_case(Def_name@1);
_ ->
<<"Unknown"/utf8>>
end;
{array, _, _, Items} ->
<<<<"List("/utf8,
(type_name(Items, <<Name/binary, "Item"/utf8>>))/binary>>/binary,
")"/utf8>>;
{empty, _} ->
<<"dynamic.Dynamic"/utf8>>;
{type, _, _, Type_} ->
case Type_ of
boolean ->
<<"Bool"/utf8>>;
string ->
<<"String"/utf8>>;
number ->
<<"Int"/utf8>>;
integer ->
<<"Int"/utf8>>;
array_type ->
<<"List(dynamic.Dynamic)"/utf8>>;
object_type ->
<<"Dict(String, dynamic.Dynamic)"/utf8>>;
null ->
<<"Nil"/utf8>>
end;
{one_of, _, _, Schemas} ->
Name;
{any_of, _, _, Schemas} ->
Name;
{all_of, _, _, Schemas} ->
Name;
{'not', _, _, Schema@1} ->
type_name(Schema@1, <<Name/binary, "Not"/utf8>>)
end,
case Nullable@1 of
true ->
<<<<"option.Option("/utf8, Name@1/binary>>/binary, ")"/utf8>>;
false ->
Name@1
end.
-file("src/mcp_toolkit/core/json_schema.gleam", 828).
-spec ensure_no_duplicate_properties(object_schema(), binary(), binary()) -> {ok,
nil} |
{error, codegen_error()}.
ensure_no_duplicate_properties(Schema, Type_name, Constructor_name) ->
Names = erlang:element(2, Schema),
Recorded = gleam@set:new(),
_pipe = gleam@list:try_fold(
Names,
Recorded,
fun(Recorded@1, Pair) ->
Field_name = justin:snake_case(erlang:element(1, Pair)),
Before = gleam@set:size(Recorded@1),
Recorded@2 = gleam@set:insert(Recorded@1, Field_name),
case Before =:= gleam@set:size(Recorded@2) of
false ->
{ok, Recorded@2};
true ->
{error,
{duplicate_property_error,
Type_name,
Constructor_name,
Field_name}}
end
end
),
gleam@result:replace(_pipe, nil).
-file("src/mcp_toolkit/core/json_schema.gleam", 901).
-spec ensure_constructor_unique(generator(), binary()) -> {ok, generator()} |
{error, codegen_error()}.
ensure_constructor_unique(Gen, Name) ->
Before = gleam@set:size(erlang:element(11, Gen)),
Constructors = gleam@set:insert(erlang:element(11, Gen), Name),
case Before =:= gleam@set:size(Constructors) of
false ->
{ok,
{generator,
erlang:element(2, Gen),
erlang:element(3, Gen),
erlang:element(4, Gen),
erlang:element(5, Gen),
erlang:element(6, Gen),
erlang:element(7, Gen),
erlang:element(8, Gen),
erlang:element(9, Gen),
erlang:element(10, Gen),
Constructors}};
true ->
{error, {duplicate_constructor_error, Name}}
end.
-file("src/mcp_toolkit/core/json_schema.gleam", 928).
-spec gen_register_nullable(generator(), boolean()) -> generator().
gen_register_nullable(Gen, Nullable) ->
case Nullable of
false ->
Gen;
true ->
{generator,
erlang:element(2, Gen),
erlang:element(3, Gen),
erlang:element(4, Gen),
true,
erlang:element(6, Gen),
erlang:element(7, Gen),
erlang:element(8, Gen),
erlang:element(9, Gen),
erlang:element(10, Gen),
erlang:element(11, Gen)}
end.
-file("src/mcp_toolkit/core/json_schema.gleam", 973).
-spec gen_add_function(generator(), binary(), binary()) -> {ok, generator()} |
{error, codegen_error()}.
gen_add_function(Gen, Name, Body) ->
Before = maps:size(erlang:element(9, Gen)),
Functions = gleam@dict:insert(erlang:element(9, Gen), Name, Body),
case maps:size(Functions) =:= Before of
false ->
{ok,
{generator,
erlang:element(2, Gen),
erlang:element(3, Gen),
erlang:element(4, Gen),
erlang:element(5, Gen),
erlang:element(6, Gen),
erlang:element(7, Gen),
erlang:element(8, Gen),
Functions,
erlang:element(10, Gen),
erlang:element(11, Gen)}};
true ->
{error, {duplicate_function_error, Name}}
end.
-file("src/mcp_toolkit/core/json_schema.gleam", 986).
-spec gen_add_type(generator(), binary(), binary()) -> {ok, generator()} |
{error, codegen_error()}.
gen_add_type(Gen, Name, Body) ->
Before = maps:size(erlang:element(8, Gen)),
Types = gleam@dict:insert(erlang:element(8, Gen), Name, Body),
case maps:size(Types) =:= Before of
false ->
{ok,
{generator,
erlang:element(2, Gen),
erlang:element(3, Gen),
erlang:element(4, Gen),
erlang:element(5, Gen),
erlang:element(6, Gen),
erlang:element(7, Gen),
Types,
erlang:element(9, Gen),
erlang:element(10, Gen),
erlang:element(11, Gen)}};
true ->
{error, {duplicate_type_error, Name}}
end.
-file("src/mcp_toolkit/core/json_schema.gleam", 913).
-spec gen_enum_type_string(generator(), binary(), list(binary())) -> {ok,
generator()} |
{error, codegen_error()}.
gen_enum_type_string(Gen, Name, Variants) ->
gleam@bool:guard(
Variants =:= [],
{error, empty_enum_error},
fun() ->
Variants@1 = begin
_pipe = Variants,
_pipe@1 = gleam@list:map(
_pipe,
fun(V) ->
<<<<" "/utf8, (justin:pascal_case(V))/binary>>/binary,
"\n"/utf8>>
end
),
gleam@string:join(_pipe@1, <<""/utf8>>)
end,
Src = <<<<<<<<"pub type "/utf8, Name/binary>>/binary, " {\n"/utf8>>/binary,
Variants@1/binary>>/binary,
"}"/utf8>>,
gen_add_type(Gen, Name, Src)
end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 999).
-spec gen_to_string(generator()) -> binary().
gen_to_string(Gen) ->
Imp = fun(Used, Module) -> case Used of
true ->
[Module];
false ->
[]
end end,
Imports = begin
_pipe = [Imp(erlang:element(2, Gen), <<"decode"/utf8>>),
Imp(erlang:element(6, Gen), <<"gleam/dict"/utf8>>),
Imp(erlang:element(4, Gen), <<"gleam/dynamic"/utf8>>),
Imp(erlang:element(3, Gen), <<"gleam/json"/utf8>>),
Imp(erlang:element(5, Gen), <<"gleam/option"/utf8>>)],
_pipe@1 = lists:append(_pipe),
_pipe@2 = gleam@list:map(
_pipe@1,
fun(M) -> <<"import "/utf8, M/binary>> end
),
gleam@string:join(_pipe@2, <<"\n"/utf8>>)
end,
Defs = fun(Items) -> _pipe@3 = Items,
_pipe@4 = maps:to_list(_pipe@3),
_pipe@5 = gleam@list:sort(
_pipe@4,
fun(A, B) ->
gleam@string:compare(erlang:element(1, A), erlang:element(1, B))
end
),
_pipe@6 = gleam@list:map(
_pipe@5,
fun(A@1) -> erlang:element(2, A@1) end
),
gleam@string:join(_pipe@6, <<"\n\n"/utf8>>) end,
Block = fun(S) -> case S of
<<""/utf8>> ->
[];
_ ->
[S]
end end,
Helper__optional_property = case erlang:element(3, Gen) andalso erlang:element(
7,
Gen
) of
false ->
[];
true ->
[<<"fn helper__optional_property(\n object: List(#(String, json.Json)),\n key: String,\n value: option.Option(a),\n to_json: fn(a) -> json.Json,\n) -> List(#(String, json.Json)) {\n case value {\n option.Some(value) -> [#(key, to_json(value)), ..object]\n option.None -> object\n }\n}"/utf8>>]
end,
Helper__dict_to_json = case erlang:element(3, Gen) andalso erlang:element(
6,
Gen
) of
false ->
[];
true ->
[<<"fn helper__dict_to_json(\n data: dict.Dict(String, t),\n to_json: fn(t) -> json.Json,\n) -> json.Json {\n data\n |> dict.to_list\n |> list.map(fn(pair) { #(pair.0, to_json(pair.1)) })\n |> json.object\n}"/utf8>>]
end,
_pipe@7 = [Block(Imports),
Block(Defs(erlang:element(8, Gen))),
Block(Defs(erlang:element(9, Gen))),
Helper__dict_to_json,
Helper__optional_property],
_pipe@8 = lists:append(_pipe@7),
gleam@string:join(_pipe@8, <<"\n\n"/utf8>>).
-file("src/mcp_toolkit/core/json_schema.gleam", 1085).
-spec en_ref(binary(), gleam@option:option(binary()), boolean()) -> {ok, out()} |
{error, codegen_error()}.
en_ref(Ref, Data, Nullable) ->
Name = case gleam@string:split(Ref, <<"/"/utf8>>) of
[<<"#"/utf8>>, <<"definitions"/utf8>>, Def_name] ->
Def_name;
[<<"#"/utf8>>, <<"$defs"/utf8>>, Def_name@1] ->
Def_name@1;
_ ->
<<"unknown"/utf8>>
end,
Src = <<(justin:snake_case(Name))/binary, "_to_json"/utf8>>,
Src@1 = case {Data, Nullable} of
{none, false} ->
Src;
{none, true} ->
<<<<"json.nullable(_, "/utf8, Src/binary>>/binary, ")"/utf8>>;
{{some, Data@1}, false} ->
<<<<<<Src/binary, "("/utf8>>/binary, Data@1/binary>>/binary,
")"/utf8>>;
{{some, Data@2}, true} ->
<<<<<<<<"json.nullable("/utf8, Data@2/binary>>/binary, ", "/utf8>>/binary,
Src/binary>>/binary,
")"/utf8>>
end,
Type_name = justin:pascal_case(Name),
Type_name@1 = case Nullable of
false ->
Type_name;
true ->
<<<<"option.Option("/utf8, Type_name/binary>>/binary, ")"/utf8>>
end,
{ok, {out, Src@1, Type_name@1}}.
-file("src/mcp_toolkit/core/json_schema.gleam", 1113).
-spec de_ref(binary(), boolean()) -> {ok, out()} | {error, codegen_error()}.
de_ref(Ref, Nullable) ->
Name = case gleam@string:split(Ref, <<"/"/utf8>>) of
[<<"#"/utf8>>, <<"definitions"/utf8>>, Def_name] ->
Def_name;
[<<"#"/utf8>>, <<"$defs"/utf8>>, Def_name@1] ->
Def_name@1;
_ ->
<<"unknown"/utf8>>
end,
Src = <<(justin:snake_case(Name))/binary, "_decoder()"/utf8>>,
Src@1 = case Nullable of
false ->
Src;
true ->
<<<<"decode.optional("/utf8, Src/binary>>/binary, ")"/utf8>>
end,
Type_name = justin:pascal_case(Name),
Type_name@1 = case Nullable of
false ->
Type_name;
true ->
<<<<"option.Option("/utf8, Type_name/binary>>/binary, ")"/utf8>>
end,
{ok, {out, Src@1, Type_name@1}}.
-file("src/mcp_toolkit/core/json_schema.gleam", 1141).
-spec pro_data_name(gleam@option:option(binary())) -> property_data_name().
pro_data_name(Name) ->
case Name of
none ->
property_data_none;
{some, N} ->
{property_data_access, N}
end.
-file("src/mcp_toolkit/core/json_schema.gleam", 1347).
-spec en_enum_string(
list(binary()),
boolean(),
gleam@option:option(binary()),
binary()
) -> {ok, out()} | {error, codegen_error()}.
en_enum_string(Variants, Nullable, Data, Position_name) ->
Type_name = Position_name,
Src = <<<<"json.string(case "/utf8,
(gleam@option:unwrap(Data, <<"data"/utf8>>))/binary>>/binary,
" {\n"/utf8>>,
Variants@1 = begin
_pipe = Variants,
_pipe@1 = gleam@list:map(
_pipe,
fun(V) ->
<<<<<<<<" "/utf8, (justin:pascal_case(V))/binary>>/binary,
" -> \""/utf8>>/binary,
V/binary>>/binary,
"\"\n"/utf8>>
end
),
erlang:list_to_binary(_pipe@1)
end,
Src@1 = <<<<Src/binary, Variants@1/binary>>/binary, " })"/utf8>>,
Src@2 = case Nullable orelse (Data =:= none) of
true ->
<<<<"fn(data) { "/utf8, Src@1/binary>>/binary, " }"/utf8>>;
false ->
Src@1
end,
Out = case Nullable of
true ->
Type_name@1 = <<<<"option.Option("/utf8, Type_name/binary>>/binary,
")"/utf8>>,
Src@3 = case Data of
{some, Data@1} ->
<<<<<<<<"json.nullable("/utf8, Data@1/binary>>/binary,
", "/utf8>>/binary,
Src@2/binary>>/binary,
")"/utf8>>;
none ->
<<<<"json.nullable(_, "/utf8, Src@2/binary>>/binary,
")"/utf8>>
end,
{out, Src@3, Type_name@1};
false ->
{out, Src@2, Type_name}
end,
{ok, Out}.
-file("src/mcp_toolkit/core/json_schema.gleam", 1438).
-spec en_nullable(binary(), binary(), boolean(), gleam@option:option(binary())) -> out().
en_nullable(Src, Type_name, Nullable, Data) ->
case Nullable of
true ->
Type_name@1 = <<<<"option.Option("/utf8, Type_name/binary>>/binary,
")"/utf8>>,
Src@1 = case Data of
{some, Data@1} ->
<<<<<<<<"json.nullable("/utf8, Data@1/binary>>/binary,
", "/utf8>>/binary,
Src/binary>>/binary,
")"/utf8>>;
none ->
<<<<"json.nullable(_, "/utf8, Src/binary>>/binary,
")"/utf8>>
end,
{out, Src@1, Type_name@1};
false ->
Src@2 = case Data of
{some, Data@2} ->
<<<<<<Src/binary, "("/utf8>>/binary, Data@2/binary>>/binary,
")"/utf8>>;
none ->
Src
end,
{out, Src@2, Type_name}
end.
-file("src/mcp_toolkit/core/json_schema.gleam", 1426).
-spec en_type(type(), boolean(), gleam@option:option(binary())) -> out().
en_type(T, Nullable, Data) ->
{Src, Type_name} = case T of
boolean ->
{<<"json.bool"/utf8>>, <<"Bool"/utf8>>};
string ->
{<<"json.string"/utf8>>, <<"String"/utf8>>};
number ->
{<<"json.int"/utf8>>, <<"Int"/utf8>>};
integer ->
{<<"json.int"/utf8>>, <<"Int"/utf8>>};
array_type ->
{<<"json.array(_, json.string)"/utf8>>, <<"List(String)"/utf8>>};
object_type ->
{<<"json.object"/utf8>>, <<"dict.Dict(String, json.Json)"/utf8>>};
null ->
{<<"fn(_) { json.null() }"/utf8>>, <<"Nil"/utf8>>}
end,
en_nullable(Src, Type_name, Nullable, Data).
-file("src/mcp_toolkit/core/json_schema.gleam", 1463).
-spec de_nullable(binary(), binary(), boolean()) -> out().
de_nullable(Src, Type_name, Nullable) ->
case Nullable of
true ->
Type_name@1 = <<<<"option.Option("/utf8, Type_name/binary>>/binary,
")"/utf8>>,
Src@1 = <<<<"decode.optional("/utf8, Src/binary>>/binary, ")"/utf8>>,
{out, Src@1, Type_name@1};
false ->
{out, Src, Type_name}
end.
-file("src/mcp_toolkit/core/json_schema.gleam", 1394).
-spec de_enum(list(binary()), boolean(), binary()) -> {ok, out()} |
{error, codegen_error()}.
de_enum(Variants, Nullable, Position_name) ->
Type_name = Position_name,
Src = <<"decode.then(decode.string, fn(s) {\n case s {\n"/utf8>>,
Variants@1 = gleam@list:map(
Variants,
fun(V) ->
<<<<<<<<" \""/utf8, V/binary>>/binary,
"\" -> decode.into("/utf8>>/binary,
(justin:pascal_case(V))/binary>>/binary,
")\n"/utf8>>
end
),
Src@1 = <<Src/binary, (erlang:list_to_binary(Variants@1))/binary>>,
Src@2 = <<<<<<Src@1/binary, " _ -> decode.fail(\""/utf8>>/binary,
Type_name/binary>>/binary,
"\")\n"/utf8>>,
Src@3 = <<Src@2/binary, " }\n })"/utf8>>,
{ok, de_nullable(Src@3, Type_name, Nullable)}.
-file("src/mcp_toolkit/core/json_schema.gleam", 1411).
-spec de_type(type(), boolean()) -> out().
de_type(T, Nullable) ->
{Src, Type_name} = case T of
boolean ->
{<<"decode.bool"/utf8>>, <<"Bool"/utf8>>};
string ->
{<<"decode.string"/utf8>>, <<"String"/utf8>>};
number ->
{<<"decode.int"/utf8>>, <<"Int"/utf8>>};
integer ->
{<<"decode.int"/utf8>>, <<"Int"/utf8>>};
array_type ->
{<<"decode.list(decode.dynamic)"/utf8>>,
<<"List(dynamic.Dynamic)"/utf8>>};
object_type ->
{<<"decode.dict(decode.string, decode.dynamic)"/utf8>>,
<<"dict.Dict(String, dynamic.Dynamic)"/utf8>>};
null ->
{<<"decode.constant(Nil, null)"/utf8>>, <<"Nil"/utf8>>}
end,
de_nullable(Src, Type_name, Nullable).
-file("src/mcp_toolkit/core/json_schema.gleam", 1181).
-spec en_composite_schema(
list(schema()),
boolean(),
gleam@option:option(binary()),
binary()
) -> {ok, out()} | {error, codegen_error()}.
en_composite_schema(Schemas, Nullable, Data, Name) ->
gleam@result:'try'(case Schemas of
[First | _] ->
{ok, First};
[] ->
{error, empty_enum_error}
end, fun(First_schema) -> en_schema(First_schema, Data, Name) end).
-file("src/mcp_toolkit/core/json_schema.gleam", 1061).
-spec en_schema(schema(), gleam@option:option(binary()), binary()) -> {ok,
out()} |
{error, codegen_error()}.
en_schema(Schema, Data, Name) ->
case Schema of
{one_of, Nullable, _, Schemas} ->
en_composite_schema(Schemas, Nullable, Data, Name);
{any_of, Nullable, _, Schemas} ->
en_composite_schema(Schemas, Nullable, Data, Name);
{all_of, Nullable, _, Schemas} ->
en_composite_schema(Schemas, Nullable, Data, Name);
{array, Nullable@1, _, Items} ->
en_array(Items, Nullable@1, Data, <<Name/binary, "Item"/utf8>>);
{empty, _} ->
{error, cannot_convert_empty_to_json_error};
{enum, Nullable@2, _, Variants} ->
en_enum_string(Variants, Nullable@2, Data, Name);
{object, Nullable@3, _, Schema@1} ->
en_object_schema(Schema@1, Nullable@3, pro_data_name(Data), Name);
{ref, Nullable@4, _, Ref} ->
en_ref(Ref, Data, Nullable@4);
{type, Nullable@5, _, Type_} ->
{ok, en_type(Type_, Nullable@5, Data)};
{'not', Nullable@6, _, Schema@2} ->
en_schema(Schema@2, Data, <<Name/binary, "Not"/utf8>>)
end.
-file("src/mcp_toolkit/core/json_schema.gleam", 935).
-spec gen_add_encoder(generator(), binary(), schema()) -> {ok, generator()} |
{error, codegen_error()}.
gen_add_encoder(Gen, Name, Schema) ->
gleam@result:'try'(
en_schema(Schema, {some, <<"data"/utf8>>}, Name),
fun(Out) ->
Name@1 = <<(justin:snake_case(Name))/binary, "_to_json"/utf8>>,
Src = <<<<<<<<<<<<"pub fn "/utf8, Name@1/binary>>/binary,
"(data: "/utf8>>/binary,
(erlang:element(3, Out))/binary>>/binary,
") -> json.Json {\n "/utf8>>/binary,
(erlang:element(2, Out))/binary>>/binary,
"\n}"/utf8>>,
gen_add_function(Gen, Name@1, Src)
end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 705).
-spec gen_encoders(generator(), binary(), root_schema()) -> {ok, generator()} |
{error, codegen_error()}.
gen_encoders(Gen, Root, Schema) ->
gen_add_encoder(Gen, Root, erlang:element(3, Schema)).
-file("src/mcp_toolkit/core/json_schema.gleam", 1254).
-spec en_object_schema(
object_schema(),
boolean(),
property_data_name(),
binary()
) -> {ok, out()} | {error, codegen_error()}.
en_object_schema(Schema, Nullable, Data, Name) ->
{object_schema, Properties, Required, _, _} = Schema,
Property_data = fun(Field_name) ->
Field_name@1 = justin:snake_case(Field_name),
case Data of
property_data_direct ->
Field_name@1;
{property_data_access, Name@1} when not Nullable ->
<<<<Name@1/binary, "."/utf8>>/binary, Field_name@1/binary>>;
_ ->
<<"data."/utf8, Field_name@1/binary>>
end
end,
gleam@result:'try'(
gleam@list:try_map(
Properties,
fun(P) ->
Name@2 = <<Name/binary,
(justin:pascal_case(erlang:element(1, P)))/binary>>,
Data@1 = Property_data(erlang:element(1, P)),
gleam@result:map(
en_schema(erlang:element(2, P), {some, Data@1}, Name@2),
fun(Out) ->
{erlang:element(1, P), erlang:element(2, Out)}
end
)
end
),
fun(Properties@1) ->
Properties@2 = begin
_pipe = Properties@1,
gleam@list:map(
_pipe,
fun(P@1) ->
<<<<<<<<"\n #(\""/utf8,
(erlang:element(1, P@1))/binary>>/binary,
"\", "/utf8>>/binary,
(erlang:element(2, P@1))/binary>>/binary,
"),"/utf8>>
end
)
end,
Src = case Properties@2 of
[] ->
<<"[]"/utf8>>;
P@2 ->
<<<<"["/utf8, (erlang:list_to_binary(P@2))/binary>>/binary,
"\n ]"/utf8>>
end,
Src@1 = <<<<"json.object("/utf8, Src/binary>>/binary, ")"/utf8>>,
Src@2 = case Nullable of
true ->
Data@2 = case Data of
{property_data_access, Name@3} ->
Name@3;
property_data_direct ->
<<"data"/utf8>>;
property_data_none ->
<<"data"/utf8>>
end,
<<<<<<<<"case "/utf8, Data@2/binary>>/binary,
" {\n option.Some(data) -> "/utf8>>/binary,
Src@1/binary>>/binary,
"\n option.None -> json.null()\n }"/utf8>>;
false ->
Src@1
end,
Src@3 = case Data of
property_data_none ->
<<<<"fn(data) { "/utf8, Src@2/binary>>/binary, " }"/utf8>>;
_ ->
Src@2
end,
Type_name = case Nullable of
true ->
<<<<"option.Option("/utf8, Name/binary>>/binary, ")"/utf8>>;
false ->
Name
end,
{ok, {out, Src@3, Type_name}}
end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 1324).
-spec en_array(schema(), boolean(), gleam@option:option(binary()), binary()) -> {ok,
out()} |
{error, codegen_error()}.
en_array(Schema, Nullable, Data, Position_name) ->
gleam@result:'try'(
en_schema(Schema, none, Position_name),
fun(_use0) ->
{out, Src, Type_name} = _use0,
Type_name@1 = <<<<"List("/utf8, Type_name/binary>>/binary,
")"/utf8>>,
Data@1 = gleam@option:unwrap(Data, <<"_"/utf8>>),
case Nullable of
false ->
Src@1 = <<<<<<<<"json.array("/utf8, Data@1/binary>>/binary,
", "/utf8>>/binary,
Src/binary>>/binary,
")"/utf8>>,
{ok, {out, Src@1, Type_name@1}};
true ->
Type_name@2 = <<<<"option.Option("/utf8,
Type_name@1/binary>>/binary,
")"/utf8>>,
Src@2 = <<<<"json.array(_, "/utf8, Src/binary>>/binary,
")"/utf8>>,
Src@3 = <<<<<<<<"json.nullable("/utf8, Data@1/binary>>/binary,
", "/utf8>>/binary,
Src@2/binary>>/binary,
")"/utf8>>,
{ok, {out, Src@3, Type_name@2}}
end
end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 1166).
-spec de_composite_schema(list(schema()), boolean(), binary()) -> {ok, out()} |
{error, codegen_error()}.
de_composite_schema(Schemas, Nullable, Name) ->
gleam@result:'try'(case Schemas of
[First | _] ->
{ok, First};
[] ->
{error, empty_enum_error}
end, fun(First_schema) -> de_schema(First_schema, Name) end).
-file("src/mcp_toolkit/core/json_schema.gleam", 1148).
-spec de_schema(schema(), binary()) -> {ok, out()} | {error, codegen_error()}.
de_schema(Schema, Name) ->
case Schema of
{one_of, Nullable, _, Schemas} ->
de_composite_schema(Schemas, Nullable, Name);
{any_of, Nullable, _, Schemas} ->
de_composite_schema(Schemas, Nullable, Name);
{all_of, Nullable, _, Schemas} ->
de_composite_schema(Schemas, Nullable, Name);
{array, Nullable@1, _, Items} ->
de_array(Items, Nullable@1, <<Name/binary, "Item"/utf8>>);
{empty, _} ->
{ok, {out, <<"decode.dynamic"/utf8>>, <<"dynamic.Dynamic"/utf8>>}};
{enum, Nullable@2, _, Variants} ->
de_enum(Variants, Nullable@2, Name);
{object, Nullable@3, _, Schema@1} ->
de_object_schema(Schema@1, Nullable@3, Name);
{ref, Nullable@4, _, Ref} ->
de_ref(Ref, Nullable@4);
{type, Nullable@5, _, Type_} ->
{ok, de_type(Type_, Nullable@5)};
{'not', Nullable@6, _, Schema@2} ->
de_schema(Schema@2, <<Name/binary, "Not"/utf8>>)
end.
-file("src/mcp_toolkit/core/json_schema.gleam", 954).
-spec gen_add_decoder(generator(), binary(), schema()) -> {ok, generator()} |
{error, codegen_error()}.
gen_add_decoder(Gen, Name, Schema) ->
gleam@result:'try'(
de_schema(Schema, Name),
fun(Out) ->
Fn_name = <<(justin:snake_case(Name))/binary, "_decoder"/utf8>>,
Src = <<<<<<<<<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"() -> decode.Decoder("/utf8>>/binary,
(erlang:element(3, Out))/binary>>/binary,
") {\n "/utf8>>/binary,
(erlang:element(2, Out))/binary>>/binary,
"\n}"/utf8>>,
gen_add_function(Gen, Name, Src)
end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 713).
-spec gen_decoders(generator(), binary(), root_schema()) -> {ok, generator()} |
{error, codegen_error()}.
gen_decoders(Gen, Root, Schema) ->
gen_add_decoder(Gen, Root, erlang:element(3, Schema)).
-file("src/mcp_toolkit/core/json_schema.gleam", 1197).
-spec de_object_schema(object_schema(), boolean(), binary()) -> {ok, out()} |
{error, codegen_error()}.
de_object_schema(Schema, Nullable, Name) ->
{object_schema, Properties, Required, _, _} = Schema,
gleam@result:'try'(
gleam@list:try_map(
Properties,
fun(Prop) ->
gleam@result:map(
de_schema(
erlang:element(2, Prop),
<<Name/binary,
(justin:pascal_case(erlang:element(1, Prop)))/binary>>
),
fun(S) ->
Is_required = gleam@list:contains(
Required,
erlang:element(1, Prop)
),
{erlang:element(1, Prop), S, not Is_required}
end
)
end
),
fun(Properties@1) ->
Params = begin
_pipe = Properties@1,
_pipe@1 = gleam@list:map(
_pipe,
fun(N) ->
Name@1 = justin:snake_case(erlang:element(1, N)),
<<<<" use "/utf8, Name@1/binary>>/binary,
" <- decode.parameter"/utf8>>
end
),
gleam@string:join(_pipe@1, <<"\n"/utf8>>)
end,
Fields = begin
_pipe@2 = Properties@1,
_pipe@3 = gleam@list:map(
_pipe@2,
fun(P) ->
Field = case erlang:element(3, P) of
true ->
<<" |> decode.optional_field(\""/utf8>>;
false ->
<<" |> decode.field(\""/utf8>>
end,
<<<<<<<<Field/binary, (erlang:element(1, P))/binary>>/binary,
"\", "/utf8>>/binary,
(erlang:element(2, (erlang:element(2, P))))/binary>>/binary,
")"/utf8>>
end
),
gleam@string:join(_pipe@3, <<"\n"/utf8>>)
end,
Keys = begin
_pipe@4 = Properties@1,
_pipe@5 = gleam@list:map(
_pipe@4,
fun(N@1) ->
<<(justin:snake_case(erlang:element(1, N@1)))/binary,
":"/utf8>>
end
),
gleam@string:join(_pipe@5, <<", "/utf8>>)
end,
Src = <<<<<<<<<<<<<<"decode.into({\n"/utf8, Params/binary>>/binary,
"\n "/utf8>>/binary,
Name/binary>>/binary,
"("/utf8>>/binary,
Keys/binary>>/binary,
")\n })\n"/utf8>>/binary,
Fields/binary>>,
{ok, de_nullable(Src, Name, Nullable)}
end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 1383).
-spec de_array(schema(), boolean(), binary()) -> {ok, out()} |
{error, codegen_error()}.
de_array(Schema, Nullable, Position_name) ->
gleam@result:'try'(
de_schema(Schema, Position_name),
fun(_use0) ->
{out, Src, Type_name} = _use0,
Type_name@1 = <<<<"List("/utf8, Type_name/binary>>/binary,
")"/utf8>>,
Src@1 = <<<<"decode.list("/utf8, Src/binary>>/binary, ")"/utf8>>,
{ok, de_nullable(Src@1, Type_name@1, Nullable)}
end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 849).
-spec type_variant(generator(), binary(), object_schema()) -> {ok,
{generator(), binary()}} |
{error, codegen_error()}.
type_variant(Gen, Name, Schema) ->
Gen@1 = case erlang:element(3, Schema) of
[] ->
Gen;
_ ->
{generator,
erlang:element(2, Gen),
erlang:element(3, Gen),
erlang:element(4, Gen),
erlang:element(5, Gen),
erlang:element(6, Gen),
true,
erlang:element(8, Gen),
erlang:element(9, Gen),
erlang:element(10, Gen),
erlang:element(11, Gen)}
end,
{object_schema, Properties, Required, _, _} = Schema,
gleam@result:'try'(
gleam@list:try_fold(
Properties,
Gen@1,
fun(Gen@2, Prop) ->
gen_type(
Gen@2,
<<Name/binary,
(justin:pascal_case(erlang:element(1, Prop)))/binary>>,
erlang:element(2, Prop)
)
end
),
fun(Gen@3) ->
Property_is_required = fun(Prop_name) ->
gleam@list:contains(Required, Prop_name)
end,
Properties@1 = begin
_pipe = Properties,
_pipe@1 = gleam@list:map(
_pipe,
fun(P) ->
Is_required = Property_is_required(erlang:element(1, P)),
{erlang:element(1, P),
erlang:element(2, P),
not Is_required}
end
),
_pipe@2 = gleam@list:sort(
_pipe@1,
fun(A, B) ->
gleam@string:compare(
erlang:element(1, A),
erlang:element(1, B)
)
end
),
_pipe@3 = gleam@list:map(
_pipe@2,
fun(P@1) ->
N = justin:snake_case(erlang:element(1, P@1)),
Type_n = type_name(
erlang:element(2, P@1),
<<Name/binary,
(justin:pascal_case(erlang:element(1, P@1)))/binary>>
),
Type_n@1 = case erlang:element(3, P@1) of
true ->
<<<<"option.Option("/utf8, Type_n/binary>>/binary,
")"/utf8>>;
false ->
Type_n
end,
<<<<<<" "/utf8, N/binary>>/binary, ": "/utf8>>/binary,
Type_n@1/binary>>
end
),
gleam@string:join(_pipe@3, <<",\n"/utf8>>)
end,
gleam@result:'try'(
ensure_constructor_unique(Gen@3, Name),
fun(Gen@4) ->
Src = <<<<<<<<" "/utf8, Name/binary>>/binary, "(\n"/utf8>>/binary,
Properties@1/binary>>/binary,
",\n )"/utf8>>,
{ok, {Gen@4, Src}}
end
)
end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 721).
-spec gen_type(generator(), binary(), schema()) -> {ok, generator()} |
{error, codegen_error()}.
gen_type(Gen, Name, Schema) ->
Name@1 = justin:pascal_case(Name),
case Schema of
{empty, _} ->
{ok,
{generator,
erlang:element(2, Gen),
erlang:element(3, Gen),
true,
erlang:element(5, Gen),
erlang:element(6, Gen),
erlang:element(7, Gen),
erlang:element(8, Gen),
erlang:element(9, Gen),
erlang:element(10, Gen),
erlang:element(11, Gen)}};
{ref, Nullable, _, _} ->
{ok, gen_register_nullable(Gen, Nullable)};
{type, Nullable@1, _, _} ->
{ok, gen_register_nullable(Gen, Nullable@1)};
{enum, Nullable@2, _, Variants} ->
Gen@1 = gen_register_nullable(Gen, Nullable@2),
gen_enum_type_string(Gen@1, Name@1, Variants);
{object, Nullable@3, _, Schema@1} ->
Gen@2 = gen_register_nullable(Gen, Nullable@3),
gen_register_object(Gen@2, Name@1, Schema@1);
{array, Nullable@4, _, Items} ->
Gen@3 = gen_register_nullable(Gen, Nullable@4),
gen_type(Gen@3, <<Name@1/binary, "Item"/utf8>>, Items);
{one_of, Nullable@5, _, Schemas} ->
Gen@4 = gen_register_nullable(Gen, Nullable@5),
gleam@list:try_fold(
Schemas,
Gen@4,
fun(Gen@5, Schema@2) ->
gen_type(Gen@5, <<Name@1/binary, "Element"/utf8>>, Schema@2)
end
);
{any_of, Nullable@5, _, Schemas} ->
Gen@4 = gen_register_nullable(Gen, Nullable@5),
gleam@list:try_fold(
Schemas,
Gen@4,
fun(Gen@5, Schema@2) ->
gen_type(Gen@5, <<Name@1/binary, "Element"/utf8>>, Schema@2)
end
);
{all_of, Nullable@5, _, Schemas} ->
Gen@4 = gen_register_nullable(Gen, Nullable@5),
gleam@list:try_fold(
Schemas,
Gen@4,
fun(Gen@5, Schema@2) ->
gen_type(Gen@5, <<Name@1/binary, "Element"/utf8>>, Schema@2)
end
);
{'not', Nullable@6, _, Schema@3} ->
Gen@6 = gen_register_nullable(Gen, Nullable@6),
gen_type(Gen@6, <<Name@1/binary, "Not"/utf8>>, Schema@3)
end.
-file("src/mcp_toolkit/core/json_schema.gleam", 814).
-spec gen_register_object(generator(), binary(), object_schema()) -> {ok,
generator()} |
{error, codegen_error()}.
gen_register_object(Gen, Name, Schema) ->
gleam@result:'try'(
ensure_no_duplicate_properties(Schema, Name, Name),
fun(_) ->
gleam@result:'try'(
type_variant(Gen, Name, Schema),
fun(_use0) ->
{Gen@1, Src} = _use0,
Src@1 = <<<<<<<<"pub type "/utf8, Name/binary>>/binary,
" {\n"/utf8>>/binary,
Src/binary>>/binary,
"\n}"/utf8>>,
Type_name = Name,
gen_add_type(Gen@1, Type_name, Src@1)
end
)
end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 682).
-spec gen_types(generator(), binary(), root_schema()) -> {ok, generator()} |
{error, codegen_error()}.
gen_types(Gen, _, Schema) ->
gleam@list:try_fold(
erlang:element(2, Schema),
Gen,
fun(Gen@1, Def) ->
gen_type(Gen@1, erlang:element(1, Def), erlang:element(2, Def))
end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 661).
-spec generate(generator(), root_schema()) -> {ok, binary()} |
{error, codegen_error()}.
generate(Gen, Schema) ->
Root = justin:pascal_case(erlang:element(10, Gen)),
gleam@result:'try'(
gen_types(Gen, Root, Schema),
fun(Gen@1) -> gleam@result:'try'(case erlang:element(2, Gen@1) of
true ->
gen_decoders(Gen@1, Root, Schema);
false ->
{ok, Gen@1}
end, fun(Gen@2) ->
gleam@result:map(case erlang:element(3, Gen@2) of
true ->
gen_encoders(Gen@2, Root, Schema);
false ->
{ok, Gen@2}
end, fun(Gen@3) -> gen_to_string(Gen@3) end)
end) end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 306).
-spec decode_object(
gleam@dynamic:dynamic_(),
gleam@dict:dict(binary(), gleam@dynamic:dynamic_())
) -> {ok, schema()} | {error, list(gleam@dynamic@decode:decode_error())}.
decode_object(_, Data) ->
gleam@result:'try'(
get_nullable(Data),
fun(Nullable) ->
gleam@result:'try'(
get_metadata(Data),
fun(Metadata) ->
Properties = case gleam_stdlib:map_get(
Data,
<<"properties"/utf8>>
) of
{ok, D} ->
decode_schema_dict(D);
{error, _} ->
{ok, []}
end,
Pattern_properties = case gleam_stdlib:map_get(
Data,
<<"patternProperties"/utf8>>
) of
{ok, D@1} ->
decode_schema_dict(D@1);
{error, _} ->
{ok, []}
end,
Required = case gleam_stdlib:map_get(
Data,
<<"required"/utf8>>
) of
{ok, D@2} ->
gleam@dynamic@decode:run(
D@2,
gleam@dynamic@decode:list(
{decoder,
fun gleam@dynamic@decode:decode_string/1}
)
);
{error, _} ->
{ok, []}
end,
Additional_properties = case gleam_stdlib:map_get(
Data,
<<"additionalProperties"/utf8>>
) of
{ok, D@3} ->
case gleam@dynamic@decode:run(
D@3,
{decoder,
fun gleam@dynamic@decode:decode_bool/1}
) of
{ok, true} ->
{ok, {some, {empty, []}}};
{ok, false} ->
{ok, none};
{error, _} ->
_pipe = decode_schema(D@3),
gleam@result:map(
_pipe,
fun(Field@0) -> {some, Field@0} end
)
end;
{error, _} ->
{ok, {some, {empty, []}}}
end,
gleam@result:'try'(
Properties,
fun(Properties@1) ->
gleam@result:'try'(
Pattern_properties,
fun(Pattern_properties@1) ->
gleam@result:'try'(
Required,
fun(Required@1) ->
gleam@result:'try'(
Additional_properties,
fun(Additional_properties@1) ->
{ok,
{object,
Nullable,
Metadata,
{object_schema,
Properties@1,
Required@1,
Additional_properties@1,
Pattern_properties@1}}}
end
)
end
)
end
)
end
)
end
)
end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 272).
-spec decode_schema(gleam@dynamic:dynamic_()) -> {ok, schema()} |
{error, list(gleam@dynamic@decode:decode_error())}.
decode_schema(Data) ->
gleam@result:'try'(
gleam@dynamic@decode:run(
Data,
gleam@dynamic@decode:dict(
{decoder, fun gleam@dynamic@decode:decode_string/1},
{decoder, fun gleam@dynamic@decode:decode_dynamic/1}
)
),
fun(Data@1) ->
Decoder = begin
_pipe = key_decoder(Data@1, <<"enum"/utf8>>, fun decode_enum/2),
_pipe@1 = gleam@result:lazy_or(
_pipe,
fun() ->
key_decoder(Data@1, <<"$ref"/utf8>>, fun decode_ref/2)
end
),
_pipe@2 = gleam@result:lazy_or(
_pipe@1,
fun() ->
key_decoder(
Data@1,
<<"items"/utf8>>,
fun decode_array/2
)
end
),
_pipe@3 = gleam@result:lazy_or(
_pipe@2,
fun() ->
key_decoder(
Data@1,
<<"properties"/utf8>>,
fun decode_object/2
)
end
),
_pipe@4 = gleam@result:lazy_or(
_pipe@3,
fun() ->
key_decoder(
Data@1,
<<"oneOf"/utf8>>,
fun decode_one_of/2
)
end
),
_pipe@5 = gleam@result:lazy_or(
_pipe@4,
fun() ->
key_decoder(
Data@1,
<<"anyOf"/utf8>>,
fun decode_any_of/2
)
end
),
_pipe@6 = gleam@result:lazy_or(
_pipe@5,
fun() ->
key_decoder(
Data@1,
<<"allOf"/utf8>>,
fun decode_all_of/2
)
end
),
_pipe@7 = gleam@result:lazy_or(
_pipe@6,
fun() ->
key_decoder(Data@1, <<"not"/utf8>>, fun decode_not/2)
end
),
_pipe@8 = gleam@result:lazy_or(
_pipe@7,
fun() ->
key_decoder(Data@1, <<"type"/utf8>>, fun decode_type/2)
end
),
gleam@result:unwrap(_pipe@8, fun() -> decode_empty(Data@1) end)
end,
Decoder()
end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 239).
-spec decode_definitions(gleam@dynamic:dynamic_()) -> {ok,
list({binary(), schema()})} |
{error, list(gleam@dynamic@decode:decode_error())}.
decode_definitions(Data) ->
gleam@result:'try'(
gleam@dynamic@decode:run(
Data,
gleam@dynamic@decode:dict(
{decoder, fun gleam@dynamic@decode:decode_string/1},
{decoder, fun gleam@dynamic@decode:decode_dynamic/1}
)
),
fun(Obj) ->
To_schema_list = fun(Map_dyn) ->
gleam@result:'try'(
gleam@dynamic@decode:run(
Map_dyn,
gleam@dynamic@decode:dict(
{decoder, fun gleam@dynamic@decode:decode_string/1},
{decoder, fun gleam@dynamic@decode:decode_dynamic/1}
)
),
fun(Entries) -> _pipe = Entries,
_pipe@1 = maps:to_list(_pipe),
gleam@list:try_map(
_pipe@1,
fun(Entry) ->
{K, V} = Entry,
_pipe@2 = decode_schema(V),
gleam@result:map(_pipe@2, fun(S) -> {K, S} end)
end
) end
)
end,
case gleam_stdlib:map_get(Obj, <<"$defs"/utf8>>) of
{ok, Defs} ->
To_schema_list(Defs);
{error, _} ->
case gleam_stdlib:map_get(Obj, <<"definitions"/utf8>>) of
{ok, Defs@1} ->
To_schema_list(Defs@1);
{error, _} ->
{ok, []}
end
end
end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 231).
-spec decoder(gleam@dynamic:dynamic_()) -> {ok, root_schema()} |
{error, list(gleam@dynamic@decode:decode_error())}.
decoder(Data) ->
gleam@result:'try'(
decode_definitions(Data),
fun(Defs) ->
gleam@result:'try'(
decode_schema(Data),
fun(Root) -> {ok, {root_schema, Defs, Root}} end
)
end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 395).
-spec decode_schema_dict(gleam@dynamic:dynamic_()) -> {ok,
list({binary(), schema()})} |
{error, list(gleam@dynamic@decode:decode_error())}.
decode_schema_dict(Data) ->
gleam@result:'try'(
gleam@dynamic@decode:run(
Data,
gleam@dynamic@decode:dict(
{decoder, fun gleam@dynamic@decode:decode_string/1},
{decoder, fun gleam@dynamic@decode:decode_dynamic/1}
)
),
fun(Entries) -> _pipe = Entries,
_pipe@1 = maps:to_list(_pipe),
gleam@list:try_map(
_pipe@1,
fun(Entry) ->
{K, V} = Entry,
_pipe@2 = decode_schema(V),
gleam@result:map(_pipe@2, fun(S) -> {K, S} end)
end
) end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 353).
-spec decode_object_schema(gleam@dynamic:dynamic_()) -> {ok, object_schema()} |
{error, list(gleam@dynamic@decode:decode_error())}.
decode_object_schema(Data) ->
gleam@result:'try'(
gleam@dynamic@decode:run(
Data,
gleam@dynamic@decode:dict(
{decoder, fun gleam@dynamic@decode:decode_string/1},
{decoder, fun gleam@dynamic@decode:decode_dynamic/1}
)
),
fun(Obj) ->
Properties = case gleam_stdlib:map_get(Obj, <<"properties"/utf8>>) of
{ok, D} ->
decode_schema_dict(D);
{error, _} ->
{ok, []}
end,
Pattern_properties = case gleam_stdlib:map_get(
Obj,
<<"patternProperties"/utf8>>
) of
{ok, D@1} ->
decode_schema_dict(D@1);
{error, _} ->
{ok, []}
end,
Required = case gleam_stdlib:map_get(Obj, <<"required"/utf8>>) of
{ok, D@2} ->
gleam@dynamic@decode:run(
D@2,
gleam@dynamic@decode:list(
{decoder, fun gleam@dynamic@decode:decode_string/1}
)
);
{error, _} ->
{ok, []}
end,
Additional_properties = case gleam_stdlib:map_get(
Obj,
<<"additionalProperties"/utf8>>
) of
{ok, D@3} ->
case gleam@dynamic@decode:run(
D@3,
{decoder, fun gleam@dynamic@decode:decode_bool/1}
) of
{ok, true} ->
{ok, {some, {empty, []}}};
{ok, false} ->
{ok, none};
{error, _} ->
_pipe = decode_schema(D@3),
gleam@result:map(
_pipe,
fun(Field@0) -> {some, Field@0} end
)
end;
{error, _} ->
{ok, {some, {empty, []}}}
end,
gleam@result:'try'(
Properties,
fun(Properties@1) ->
gleam@result:'try'(
Pattern_properties,
fun(Pattern_properties@1) ->
gleam@result:'try'(
Required,
fun(Required@1) ->
gleam@result:'try'(
Additional_properties,
fun(Additional_properties@1) ->
{ok,
{object_schema,
Properties@1,
Required@1,
Additional_properties@1,
Pattern_properties@1}}
end
)
end
)
end
)
end
)
end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 410).
-spec decode_array(
gleam@dynamic:dynamic_(),
gleam@dict:dict(binary(), gleam@dynamic:dynamic_())
) -> {ok, schema()} | {error, list(gleam@dynamic@decode:decode_error())}.
decode_array(Items, Data) ->
gleam@result:'try'(
get_nullable(Data),
fun(Nullable) ->
gleam@result:'try'(
get_metadata(Data),
fun(Metadata) -> _pipe = decode_schema(Items),
gleam@result:map(
_pipe,
fun(_capture) ->
{array, Nullable, Metadata, _capture}
end
) end
)
end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 420).
-spec decode_one_of(
gleam@dynamic:dynamic_(),
gleam@dict:dict(binary(), gleam@dynamic:dynamic_())
) -> {ok, schema()} | {error, list(gleam@dynamic@decode:decode_error())}.
decode_one_of(Schemas, Data) ->
gleam@result:'try'(
get_nullable(Data),
fun(Nullable) ->
gleam@result:'try'(
get_metadata(Data),
fun(Metadata) ->
gleam@result:'try'(
gleam@dynamic@decode:run(
Schemas,
gleam@dynamic@decode:list(
{decoder,
fun gleam@dynamic@decode:decode_dynamic/1}
)
),
fun(Schema_dyns) ->
gleam@result:'try'(
gleam@list:try_map(
Schema_dyns,
fun decode_schema/1
),
fun(Schemas@1) ->
{ok,
{one_of, Nullable, Metadata, Schemas@1}}
end
)
end
)
end
)
end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 431).
-spec decode_all_of(
gleam@dynamic:dynamic_(),
gleam@dict:dict(binary(), gleam@dynamic:dynamic_())
) -> {ok, schema()} | {error, list(gleam@dynamic@decode:decode_error())}.
decode_all_of(Schemas, Data) ->
gleam@result:'try'(
get_nullable(Data),
fun(Nullable) ->
gleam@result:'try'(
get_metadata(Data),
fun(Metadata) ->
gleam@result:'try'(
gleam@dynamic@decode:run(
Schemas,
gleam@dynamic@decode:list(
{decoder,
fun gleam@dynamic@decode:decode_dynamic/1}
)
),
fun(Schema_dyns) ->
gleam@result:'try'(
gleam@list:try_map(
Schema_dyns,
fun decode_schema/1
),
fun(Schemas@1) ->
{ok,
{all_of, Nullable, Metadata, Schemas@1}}
end
)
end
)
end
)
end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 442).
-spec decode_any_of(
gleam@dynamic:dynamic_(),
gleam@dict:dict(binary(), gleam@dynamic:dynamic_())
) -> {ok, schema()} | {error, list(gleam@dynamic@decode:decode_error())}.
decode_any_of(Schemas, Data) ->
gleam@result:'try'(
get_nullable(Data),
fun(Nullable) ->
gleam@result:'try'(
get_metadata(Data),
fun(Metadata) ->
gleam@result:'try'(
gleam@dynamic@decode:run(
Schemas,
gleam@dynamic@decode:list(
{decoder,
fun gleam@dynamic@decode:decode_dynamic/1}
)
),
fun(Schema_dyns) ->
gleam@result:'try'(
gleam@list:try_map(
Schema_dyns,
fun decode_schema/1
),
fun(Schemas@1) ->
{ok,
{any_of, Nullable, Metadata, Schemas@1}}
end
)
end
)
end
)
end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 453).
-spec decode_not(
gleam@dynamic:dynamic_(),
gleam@dict:dict(binary(), gleam@dynamic:dynamic_())
) -> {ok, schema()} | {error, list(gleam@dynamic@decode:decode_error())}.
decode_not(Schema, Data) ->
gleam@result:'try'(
get_nullable(Data),
fun(Nullable) ->
gleam@result:'try'(
get_metadata(Data),
fun(Metadata) ->
gleam@result:'try'(
decode_schema(Schema),
fun(Schema@1) ->
{ok, {'not', Nullable, Metadata, Schema@1}}
end
)
end
)
end
).
-file("src/mcp_toolkit/core/json_schema.gleam", 112).
-spec object_schema_to_json(object_schema()) -> list({binary(),
gleam@json:json()}).
object_schema_to_json(Schema) ->
Props_json = fun(Props) ->
gleam@json:object(
gleam@list:map(
Props,
fun(Property) ->
{erlang:element(1, Property),
gleam@json:object(
schema_to_json(erlang:element(2, Property))
)}
end
)
)
end,
{object_schema,
Properties,
Required,
Additional_properties,
Pattern_properties} = Schema,
Data = [],
Data@1 = case Pattern_properties of
[] ->
Data;
P ->
[{<<"patternProperties"/utf8>>, Props_json(P)} | Data]
end,
Data@2 = case Additional_properties of
none ->
Data@1;
{some, Schema@1} ->
[{<<"additionalProperties"/utf8>>,
gleam@json:object(schema_to_json(Schema@1))} |
Data@1]
end,
Data@3 = case Required of
[] ->
Data@2;
R ->
[{<<"required"/utf8>>, gleam@json:array(R, fun gleam@json:string/1)} |
Data@2]
end,
Data@4 = case Properties of
[] ->
Data@3;
P@1 ->
[{<<"properties"/utf8>>, Props_json(P@1)} | Data@3]
end,
Data@4.
-file("src/mcp_toolkit/core/json_schema.gleam", 156).
-spec schema_to_json(schema()) -> list({binary(), gleam@json:json()}).
schema_to_json(Schema) ->
case Schema of
{empty, Metadata} ->
_pipe = [],
add_metadata(_pipe, Metadata);
{ref, Nullable, Metadata@1, Ref} ->
_pipe@1 = [{<<"$ref"/utf8>>, gleam@json:string(Ref)}],
_pipe@2 = add_nullable(_pipe@1, Nullable),
add_metadata(_pipe@2, Metadata@1);
{type, Nullable@1, Metadata@2, Type_} ->
_pipe@3 = [{<<"type"/utf8>>, type_to_json(Type_)}],
_pipe@4 = add_nullable(_pipe@3, Nullable@1),
add_metadata(_pipe@4, Metadata@2);
{enum, Nullable@2, Metadata@3, Variants} ->
_pipe@5 = [{<<"enum"/utf8>>,
gleam@json:array(Variants, fun gleam@json:string/1)}],
_pipe@6 = add_nullable(_pipe@5, Nullable@2),
add_metadata(_pipe@6, Metadata@3);
{array, Nullable@3, Metadata@4, Items} ->
_pipe@7 = [{<<"items"/utf8>>,
gleam@json:object(schema_to_json(Items))}],
_pipe@8 = add_nullable(_pipe@7, Nullable@3),
add_metadata(_pipe@8, Metadata@4);
{object, Nullable@4, Metadata@5, Schema@1} ->
_pipe@9 = object_schema_to_json(Schema@1),
_pipe@10 = add_nullable(_pipe@9, Nullable@4),
add_metadata(_pipe@10, Metadata@5);
{one_of, Nullable@5, Metadata@6, Schemas} ->
_pipe@11 = [{<<"oneOf"/utf8>>,
gleam@json:array(
Schemas,
fun(S) -> gleam@json:object(schema_to_json(S)) end
)}],
_pipe@12 = add_nullable(_pipe@11, Nullable@5),
add_metadata(_pipe@12, Metadata@6);
{all_of, Nullable@6, Metadata@7, Schemas@1} ->
_pipe@13 = [{<<"allOf"/utf8>>,
gleam@json:array(
Schemas@1,
fun(S@1) -> gleam@json:object(schema_to_json(S@1)) end
)}],
_pipe@14 = add_nullable(_pipe@13, Nullable@6),
add_metadata(_pipe@14, Metadata@7);
{any_of, Nullable@7, Metadata@8, Schemas@2} ->
_pipe@15 = [{<<"anyOf"/utf8>>,
gleam@json:array(
Schemas@2,
fun(S@2) -> gleam@json:object(schema_to_json(S@2)) end
)}],
_pipe@16 = add_nullable(_pipe@15, Nullable@7),
add_metadata(_pipe@16, Metadata@8);
{'not', Nullable@8, Metadata@9, Schema@2} ->
_pipe@17 = [{<<"not"/utf8>>,
gleam@json:object(schema_to_json(Schema@2))}],
_pipe@18 = add_nullable(_pipe@17, Nullable@8),
add_metadata(_pipe@18, Metadata@9)
end.
-file("src/mcp_toolkit/core/json_schema.gleam", 96).
-spec to_json(root_schema()) -> gleam@json:json().
to_json(Schema) ->
Properties = schema_to_json(erlang:element(3, Schema)),
Properties@1 = case erlang:element(2, Schema) of
[] ->
Properties;
Definitions ->
Definitions@1 = gleam@list:map(
Definitions,
fun(Definition) ->
{erlang:element(1, Definition),
gleam@json:object(
schema_to_json(erlang:element(2, Definition))
)}
end
),
[{<<"$defs"/utf8>>, gleam@json:object(Definitions@1)} | Properties]
end,
gleam@json:object(Properties@1).