-module(mochi@types). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/mochi/types.gleam"). -export([to_dynamic/1, record/1, option/1, field/2, object/1, description/2, field_description/2, deprecated/2, deprecated_no_reason/1, string/3, id/3, optional_id/3, int/3, float/3, bool/3, datetime/3, optional_datetime/3, date/3, optional_date/3, uuid/3, optional_uuid/3, email/3, optional_email/3, url/3, optional_url/3, json/3, optional_json/3, optional_string/3, optional_int/3, optional_float/3, optional_bool/3, nullable/1, list_string/3, list_int/3, list_float/3, list_bool/3, list_id/3, non_null_list_string/3, non_null_list_int/3, non_null_list_float/3, object_field/4, list_object/4, non_null_field/4, non_null_string/3, non_null_int/3, non_null_float/3, non_null_bool/3, field_with_args/6, build_direct/1, encoder/1, build/2, build_with_encoder/2, enum_type/1, enum_description/2, value/2, value_with_desc/3, deprecated_value/2, deprecated_value_with_reason/3, build_enum/1, enum_mapping/2, enum_mapping_with_desc/3, enum_from_mappings/2, enum_from_mappings_with_desc/3, input/1, input_description/2, input_field/4, input_string/3, input_int/3, input_float/3, input_bool/3, input_id/3, input_optional_string/3, input_optional_int/3, input_optional_float/3, input_optional_bool/3, input_field_with_default/5, build_input/1]). -export_type([type_builder/1, type_field/1, enum_builder/0, enum_value/0, enum_mapping/1, input_builder/0, input_field/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( " Type definition helpers for Code First GraphQL.\n" "\n" " This module provides builders for creating GraphQL types from Gleam types\n" " with minimal boilerplate, plus helpers for Dynamic conversion.\n" "\n" " ## Object Type Builder\n" "\n" " ```gleam\n" " let user_type = types.object(\"User\")\n" " |> types.description(\"A user in the system\")\n" " |> types.id(\"id\", fn(u: User) { u.id })\n" " |> types.string(\"name\", fn(u: User) { u.name })\n" " |> types.int(\"age\", fn(u: User) { u.age })\n" " |> types.build(decode_user)\n" " ```\n" "\n" " ## Enum Builder\n" "\n" " ```gleam\n" " let role_enum = types.enum_type(\"Role\")\n" " |> types.value(\"ADMIN\")\n" " |> types.value(\"USER\")\n" " |> types.deprecated_value_with_reason(\"GUEST\", \"Use USER instead\")\n" " |> types.build_enum\n" " ```\n" "\n" " ## Dynamic Conversion Helpers\n" "\n" " Use these when building DataLoader encoders or custom resolvers:\n" "\n" " ```gleam\n" " fn user_to_dynamic(u: User) -> Dynamic {\n" " types.record([\n" " types.field(\"id\", u.id),\n" " types.field(\"name\", u.name),\n" " #(\"profile\", profile_to_dynamic(u.profile)),\n" " #(\"age\", types.option(u.age)), // Option(Int) -> null if None\n" " ])\n" " }\n" " ```\n" ). -type type_builder(FKX) :: {type_builder, binary(), gleam@option:option(binary()), list(type_field(FKX))}. -type type_field(FKY) :: {type_field, binary(), gleam@option:option(binary()), mochi@schema:field_type(), fun((FKY) -> gleam@dynamic:dynamic_()), boolean(), gleam@option:option(binary())} | {type_field_with_args, binary(), gleam@option:option(binary()), mochi@schema:field_type(), list(mochi@schema:argument_definition()), fun((FKY, mochi@args:args(), mochi@schema:execution_context()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}), boolean(), gleam@option:option(binary())}. -type enum_builder() :: {enum_builder, binary(), gleam@option:option(binary()), list(enum_value())}. -type enum_value() :: {enum_value, binary(), gleam@option:option(binary()), boolean(), gleam@option:option(binary())}. -type enum_mapping(FKZ) :: {enum_mapping, FKZ, binary(), gleam@option:option(binary())}. -type input_builder() :: {input_builder, binary(), gleam@option:option(binary()), list(input_field())}. -type input_field() :: {input_field, binary(), gleam@option:option(binary()), mochi@schema:field_type(), gleam@option:option(gleam@dynamic:dynamic_())}. -file("src/mochi/types.gleam", 61). ?DOC( " Convert any Gleam value to Dynamic\n" " This uses unsafe_coerce under the hood\n" ). -spec to_dynamic(any()) -> gleam@dynamic:dynamic_(). to_dynamic(Value) -> gleam_stdlib:identity(Value). -file("src/mochi/types.gleam", 81). ?DOC( " Build a Dynamic dict from a list of field tuples\n" "\n" " This is a convenience helper for creating DataLoader encoders.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " fn user_to_dynamic(u: User) -> Dynamic {\n" " types.record([\n" " #(\"id\", types.to_dynamic(u.id)),\n" " #(\"name\", types.to_dynamic(u.name)),\n" " #(\"email\", types.to_dynamic(u.email)),\n" " ])\n" " }\n" " ```\n" ). -spec record(list({binary(), gleam@dynamic:dynamic_()})) -> gleam@dynamic:dynamic_(). record(Fields) -> gleam_stdlib:identity(maps:from_list(Fields)). -file("src/mochi/types.gleam", 92). ?DOC( " Convert an Option to Dynamic (None becomes Nil/null)\n" "\n" " ## Example\n" "\n" " ```gleam\n" " #(\"age\", types.option(user.age))\n" " ```\n" ). -spec option(gleam@option:option(any())) -> gleam@dynamic:dynamic_(). option(Opt) -> case Opt of {some, V} -> gleam_stdlib:identity(V); none -> gleam_stdlib:identity(nil) end. -file("src/mochi/types.gleam", 109). ?DOC( " Shorthand: wrap a value in to_dynamic with a field name\n" "\n" " ## Example\n" "\n" " ```gleam\n" " types.record([\n" " types.field(\"id\", user.id),\n" " types.field(\"name\", user.name),\n" " ])\n" " ```\n" ). -spec field(binary(), any()) -> {binary(), gleam@dynamic:dynamic_()}. field(Name, Value) -> {Name, gleam_stdlib:identity(Value)}. -file("src/mochi/types.gleam", 150). ?DOC(" Create a new type builder\n"). -spec object(binary()) -> type_builder(any()). object(Name) -> {type_builder, Name, none, []}. -file("src/mochi/types.gleam", 155). ?DOC(" Add description to type\n"). -spec description(type_builder(FLI), binary()) -> type_builder(FLI). description(Builder, Desc) -> {type_builder, erlang:element(2, Builder), {some, Desc}, erlang:element(4, Builder)}. -file("src/mochi/types.gleam", 194). -spec set_field_description(type_field(FLU), binary()) -> type_field(FLU). set_field_description(Field, Desc) -> case Field of {type_field, _, _, _, _, _, _} -> {type_field, erlang:element(2, Field), {some, Desc}, erlang:element(4, Field), erlang:element(5, Field), erlang:element(6, Field), erlang:element(7, Field)}; {type_field_with_args, _, _, _, _, _, _, _} -> {type_field_with_args, erlang:element(2, Field), {some, Desc}, erlang:element(4, Field), erlang:element(5, Field), erlang:element(6, Field), erlang:element(7, Field), erlang:element(8, Field)} end. -file("src/mochi/types.gleam", 183). -spec field_description(type_builder(FLR), binary()) -> type_builder(FLR). field_description(Builder, Desc) -> case erlang:element(4, Builder) of [] -> Builder; [F | Rest] -> {type_builder, erlang:element(2, Builder), erlang:element(3, Builder), [set_field_description(F, Desc) | Rest]} end. -file("src/mochi/types.gleam", 201). -spec mark_deprecated(type_field(FLX), boolean(), gleam@option:option(binary())) -> type_field(FLX). mark_deprecated(Field, Is_deprecated, Reason) -> case Field of {type_field, _, _, _, _, _, _} -> {type_field, erlang:element(2, Field), erlang:element(3, Field), erlang:element(4, Field), erlang:element(5, Field), Is_deprecated, Reason}; {type_field_with_args, _, _, _, _, _, _, _} -> {type_field_with_args, erlang:element(2, Field), erlang:element(3, Field), erlang:element(4, Field), erlang:element(5, Field), erlang:element(6, Field), Is_deprecated, Reason} end. -file("src/mochi/types.gleam", 160). ?DOC(" Mark the most recently added field as deprecated with a reason.\n"). -spec deprecated(type_builder(FLL), binary()) -> type_builder(FLL). deprecated(Builder, Reason) -> case erlang:element(4, Builder) of [] -> Builder; [Field | Rest] -> {type_builder, erlang:element(2, Builder), erlang:element(3, Builder), [mark_deprecated(Field, true, {some, Reason}) | Rest]} end. -file("src/mochi/types.gleam", 172). ?DOC(" Mark the most recently added field as deprecated without a reason.\n"). -spec deprecated_no_reason(type_builder(FLO)) -> type_builder(FLO). deprecated_no_reason(Builder) -> case erlang:element(4, Builder) of [] -> Builder; [Field | Rest] -> {type_builder, erlang:element(2, Builder), erlang:element(3, Builder), [mark_deprecated(Field, true, none) | Rest]} end. -file("src/mochi/types.gleam", 222). -spec add_field( type_builder(FMB), binary(), gleam@option:option(binary()), mochi@schema:field_type(), fun((FMB) -> gleam@dynamic:dynamic_()) ) -> type_builder(FMB). add_field(Builder, Name, Description, Field_type, Extractor) -> {type_builder, erlang:element(2, Builder), erlang:element(3, Builder), [{type_field, Name, Description, Field_type, Extractor, false, none} | erlang:element(4, Builder)]}. -file("src/mochi/types.gleam", 243). ?DOC(" Add a string field\n"). -spec string(type_builder(FMF), binary(), fun((FMF) -> binary())) -> type_builder(FMF). string(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:string_type(), fun(A) -> gleam_stdlib:identity(Extractor(A)) end ). -file("src/mochi/types.gleam", 254). ?DOC(" Add an ID field\n"). -spec id(type_builder(FMI), binary(), fun((FMI) -> binary())) -> type_builder(FMI). id(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:non_null(mochi@schema:id_type()), fun(A) -> gleam_stdlib:identity(Extractor(A)) end ). -file("src/mochi/types.gleam", 265). ?DOC(" Add a nullable ID field\n"). -spec optional_id( type_builder(FML), binary(), fun((FML) -> gleam@option:option(binary())) ) -> type_builder(FML). optional_id(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:id_type(), fun(A) -> option(Extractor(A)) end ). -file("src/mochi/types.gleam", 276). ?DOC(" Add an int field\n"). -spec int(type_builder(FMP), binary(), fun((FMP) -> integer())) -> type_builder(FMP). int(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:int_type(), fun(A) -> gleam_stdlib:identity(Extractor(A)) end ). -file("src/mochi/types.gleam", 287). ?DOC(" Add a float field\n"). -spec float(type_builder(FMS), binary(), fun((FMS) -> float())) -> type_builder(FMS). float(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:float_type(), fun(A) -> gleam_stdlib:identity(Extractor(A)) end ). -file("src/mochi/types.gleam", 298). ?DOC(" Add a boolean field\n"). -spec bool(type_builder(FMV), binary(), fun((FMV) -> boolean())) -> type_builder(FMV). bool(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:boolean_type(), fun(A) -> gleam_stdlib:identity(Extractor(A)) end ). -file("src/mochi/types.gleam", 312). -spec datetime(type_builder(FMY), binary(), fun((FMY) -> binary())) -> type_builder(FMY). datetime(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:datetime_type(), fun(A) -> gleam_stdlib:identity(Extractor(A)) end ). -file("src/mochi/types.gleam", 322). -spec optional_datetime( type_builder(FNB), binary(), fun((FNB) -> gleam@option:option(binary())) ) -> type_builder(FNB). optional_datetime(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:datetime_type(), fun(A) -> option(Extractor(A)) end ). -file("src/mochi/types.gleam", 332). -spec date(type_builder(FNF), binary(), fun((FNF) -> binary())) -> type_builder(FNF). date(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:date_type(), fun(A) -> gleam_stdlib:identity(Extractor(A)) end ). -file("src/mochi/types.gleam", 342). -spec optional_date( type_builder(FNI), binary(), fun((FNI) -> gleam@option:option(binary())) ) -> type_builder(FNI). optional_date(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:date_type(), fun(A) -> option(Extractor(A)) end ). -file("src/mochi/types.gleam", 352). -spec uuid(type_builder(FNM), binary(), fun((FNM) -> binary())) -> type_builder(FNM). uuid(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:uuid_type(), fun(A) -> gleam_stdlib:identity(Extractor(A)) end ). -file("src/mochi/types.gleam", 362). -spec optional_uuid( type_builder(FNP), binary(), fun((FNP) -> gleam@option:option(binary())) ) -> type_builder(FNP). optional_uuid(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:uuid_type(), fun(A) -> option(Extractor(A)) end ). -file("src/mochi/types.gleam", 372). -spec email(type_builder(FNT), binary(), fun((FNT) -> binary())) -> type_builder(FNT). email(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:email_type(), fun(A) -> gleam_stdlib:identity(Extractor(A)) end ). -file("src/mochi/types.gleam", 382). -spec optional_email( type_builder(FNW), binary(), fun((FNW) -> gleam@option:option(binary())) ) -> type_builder(FNW). optional_email(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:email_type(), fun(A) -> option(Extractor(A)) end ). -file("src/mochi/types.gleam", 392). -spec url(type_builder(FOA), binary(), fun((FOA) -> binary())) -> type_builder(FOA). url(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:url_type(), fun(A) -> gleam_stdlib:identity(Extractor(A)) end ). -file("src/mochi/types.gleam", 402). -spec optional_url( type_builder(FOD), binary(), fun((FOD) -> gleam@option:option(binary())) ) -> type_builder(FOD). optional_url(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:url_type(), fun(A) -> option(Extractor(A)) end ). -file("src/mochi/types.gleam", 412). -spec json(type_builder(FOH), binary(), fun((FOH) -> gleam@dynamic:dynamic_())) -> type_builder(FOH). json(Builder, Name, Extractor) -> add_field(Builder, Name, none, mochi@schema:json_type(), Extractor). -file("src/mochi/types.gleam", 420). -spec optional_json( type_builder(FOK), binary(), fun((FOK) -> gleam@option:option(gleam@dynamic:dynamic_())) ) -> type_builder(FOK). optional_json(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:json_type(), fun(A) -> option(Extractor(A)) end ). -file("src/mochi/types.gleam", 432). ?DOC( " Add an optional string field. `None` becomes JSON `null`; `Some(v)` becomes\n" " the string value. Use this for nullable GraphQL fields.\n" ). -spec optional_string( type_builder(FOO), binary(), fun((FOO) -> gleam@option:option(binary())) ) -> type_builder(FOO). optional_string(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:string_type(), fun(A) -> option(Extractor(A)) end ). -file("src/mochi/types.gleam", 444). ?DOC( " Add an optional int field. `None` becomes JSON `null`; `Some(v)` becomes\n" " the int value.\n" ). -spec optional_int( type_builder(FOS), binary(), fun((FOS) -> gleam@option:option(integer())) ) -> type_builder(FOS). optional_int(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:int_type(), fun(A) -> option(Extractor(A)) end ). -file("src/mochi/types.gleam", 456). ?DOC( " Add an optional float field. `None` becomes JSON `null`; `Some(v)` becomes\n" " the float value.\n" ). -spec optional_float( type_builder(FOW), binary(), fun((FOW) -> gleam@option:option(float())) ) -> type_builder(FOW). optional_float(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:float_type(), fun(A) -> option(Extractor(A)) end ). -file("src/mochi/types.gleam", 468). ?DOC( " Add an optional bool field. `None` becomes JSON `null`; `Some(v)` becomes\n" " the bool value.\n" ). -spec optional_bool( type_builder(FPA), binary(), fun((FPA) -> gleam@option:option(boolean())) ) -> type_builder(FPA). optional_bool(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:boolean_type(), fun(A) -> option(Extractor(A)) end ). -file("src/mochi/types.gleam", 499). ?DOC( " A decoder that returns `None` when the value is nil/null and otherwise runs\n" " the inner decoder.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " use email <- decode.optional_field(\"email\", None, types.nullable(decode.string))\n" " ```\n" ). -spec nullable(gleam@dynamic@decode:decoder(FPE)) -> gleam@dynamic@decode:decoder(gleam@option:option(FPE)). nullable(Inner) -> gleam@dynamic@decode:optional(Inner). -file("src/mochi/types.gleam", 506). ?DOC(" Add a list of strings field\n"). -spec list_string(type_builder(FPI), binary(), fun((FPI) -> list(binary()))) -> type_builder(FPI). list_string(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:list_type(mochi@schema:string_type()), fun(A) -> gleam_stdlib:identity(Extractor(A)) end ). -file("src/mochi/types.gleam", 517). ?DOC(" Add a list of ints field\n"). -spec list_int(type_builder(FPM), binary(), fun((FPM) -> list(integer()))) -> type_builder(FPM). list_int(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:list_type(mochi@schema:int_type()), fun(A) -> gleam_stdlib:identity(Extractor(A)) end ). -file("src/mochi/types.gleam", 527). -spec list_float(type_builder(FPQ), binary(), fun((FPQ) -> list(float()))) -> type_builder(FPQ). list_float(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:list_type(mochi@schema:float_type()), fun(A) -> gleam_stdlib:identity(Extractor(A)) end ). -file("src/mochi/types.gleam", 537). -spec list_bool(type_builder(FPU), binary(), fun((FPU) -> list(boolean()))) -> type_builder(FPU). list_bool(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:list_type(mochi@schema:boolean_type()), fun(A) -> gleam_stdlib:identity(Extractor(A)) end ). -file("src/mochi/types.gleam", 547). -spec list_id(type_builder(FPY), binary(), fun((FPY) -> list(binary()))) -> type_builder(FPY). list_id(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:list_type(mochi@schema:id_type()), fun(A) -> gleam_stdlib:identity(Extractor(A)) end ). -file("src/mochi/types.gleam", 557). -spec non_null_list_string( type_builder(FQC), binary(), fun((FQC) -> list(binary())) ) -> type_builder(FQC). non_null_list_string(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:non_null( mochi@schema:list_type(mochi@schema:string_type()) ), fun(A) -> gleam_stdlib:identity(Extractor(A)) end ). -file("src/mochi/types.gleam", 571). -spec non_null_list_int( type_builder(FQG), binary(), fun((FQG) -> list(integer())) ) -> type_builder(FQG). non_null_list_int(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:non_null(mochi@schema:list_type(mochi@schema:int_type())), fun(A) -> gleam_stdlib:identity(Extractor(A)) end ). -file("src/mochi/types.gleam", 585). -spec non_null_list_float( type_builder(FQK), binary(), fun((FQK) -> list(float())) ) -> type_builder(FQK). non_null_list_float(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:non_null(mochi@schema:list_type(mochi@schema:float_type())), fun(A) -> gleam_stdlib:identity(Extractor(A)) end ). -file("src/mochi/types.gleam", 600). ?DOC(" Add a related object field\n"). -spec object_field( type_builder(FQO), binary(), binary(), fun((FQO) -> gleam@dynamic:dynamic_()) ) -> type_builder(FQO). object_field(Builder, Name, Type_name, Extractor) -> add_field( Builder, Name, none, mochi@schema:named_type(Type_name), Extractor ). -file("src/mochi/types.gleam", 610). ?DOC(" Add a list of related objects field\n"). -spec list_object( type_builder(FQR), binary(), binary(), fun((FQR) -> gleam@dynamic:dynamic_()) ) -> type_builder(FQR). list_object(Builder, Name, Type_name, Extractor) -> add_field( Builder, Name, none, mochi@schema:list_type(mochi@schema:named_type(Type_name)), Extractor ). -file("src/mochi/types.gleam", 626). ?DOC(" Add a non-null field\n"). -spec non_null_field( type_builder(FQU), binary(), mochi@schema:field_type(), fun((FQU) -> gleam@dynamic:dynamic_()) ) -> type_builder(FQU). non_null_field(Builder, Name, Field_type, Extractor) -> add_field(Builder, Name, none, mochi@schema:non_null(Field_type), Extractor). -file("src/mochi/types.gleam", 640). ?DOC(" Add a non-null string field\n"). -spec non_null_string(type_builder(FQX), binary(), fun((FQX) -> binary())) -> type_builder(FQX). non_null_string(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:non_null(mochi@schema:string_type()), fun(A) -> gleam_stdlib:identity(Extractor(A)) end ). -file("src/mochi/types.gleam", 651). ?DOC(" Add a non-null int field\n"). -spec non_null_int(type_builder(FRA), binary(), fun((FRA) -> integer())) -> type_builder(FRA). non_null_int(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:non_null(mochi@schema:int_type()), fun(A) -> gleam_stdlib:identity(Extractor(A)) end ). -file("src/mochi/types.gleam", 662). ?DOC(" Add a non-null float field\n"). -spec non_null_float(type_builder(FRD), binary(), fun((FRD) -> float())) -> type_builder(FRD). non_null_float(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:non_null(mochi@schema:float_type()), fun(A) -> gleam_stdlib:identity(Extractor(A)) end ). -file("src/mochi/types.gleam", 673). ?DOC(" Add a non-null bool field\n"). -spec non_null_bool(type_builder(FRG), binary(), fun((FRG) -> boolean())) -> type_builder(FRG). non_null_bool(Builder, Name, Extractor) -> add_field( Builder, Name, none, mochi@schema:non_null(mochi@schema:boolean_type()), fun(A) -> gleam_stdlib:identity(Extractor(A)) end ). -file("src/mochi/types.gleam", 702). ?DOC( " Add a field with arguments and custom resolver\n" "\n" " ```gleam\n" " types.object(\"User\")\n" " |> types.field_with_args(\n" " name: \"posts\",\n" " returns: schema.list_type(schema.named_type(\"Post\")),\n" " args: [schema.arg(\"limit\", schema.int_type())],\n" " desc: \"User's posts with optional limit\",\n" " resolve: fn(user, args, ctx) {\n" " let limit = query.get_optional_int(args, \"limit\")\n" " get_user_posts(user.id, limit)\n" " },\n" " )\n" " ```\n" ). -spec field_with_args( type_builder(FRJ), binary(), mochi@schema:field_type(), list(mochi@schema:argument_definition()), binary(), fun((FRJ, mochi@args:args(), mochi@schema:execution_context()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}) ) -> type_builder(FRJ). field_with_args(Builder, Name, Field_type, Args, Description, Resolver) -> Field = {type_field_with_args, Name, {some, Description}, Field_type, Args, Resolver, false, none}, {type_builder, erlang:element(2, Builder), erlang:element(3, Builder), [Field | erlang:element(4, Builder)]}. -file("src/mochi/types.gleam", 829). -spec apply_deprecation( mochi@schema:field_definition(), boolean(), gleam@option:option(binary()) ) -> mochi@schema:field_definition(). apply_deprecation(Field, Is_deprecated, Deprecation_reason) -> case Is_deprecated of false -> Field; true -> case Deprecation_reason of {some, Reason} -> mochi@schema:deprecated(Field, Reason); none -> mochi@schema:deprecated_no_reason(Field) end end. -file("src/mochi/types.gleam", 844). -spec to_field_def_direct(type_field(any())) -> mochi@schema:field_definition(). to_field_def_direct(F) -> case F of {type_field, Name, Description, Field_type, Extractor, Is_deprecated, Deprecation_reason} -> Resolver = fun(Info) -> case erlang:element(2, Info) of {some, Parent_dyn} -> {ok, Extractor(gleam_stdlib:identity(Parent_dyn))}; none -> {error, <<"No parent value"/utf8>>} end end, Base = begin _pipe = mochi@schema:field_def(Name, Field_type), mochi@schema:resolver(_pipe, Resolver) end, With_desc = case Description of {some, Desc} -> mochi@schema:field_description(Base, Desc); none -> Base end, apply_deprecation(With_desc, Is_deprecated, Deprecation_reason); {type_field_with_args, Name@1, Description@1, Field_type@1, Args, Field_resolver, Is_deprecated@1, Deprecation_reason@1} -> Resolver@1 = fun(Info@1) -> case erlang:element(2, Info@1) of {some, Parent_dyn@1} -> Field_resolver( gleam_stdlib:identity(Parent_dyn@1), erlang:element(4, Info@1), erlang:element(5, Info@1) ); none -> {error, <<"No parent value"/utf8>>} end end, Base@1 = begin _pipe@1 = mochi@schema:field_def(Name@1, Field_type@1), mochi@schema:resolver(_pipe@1, Resolver@1) end, With_args = gleam@list:fold( Args, Base@1, fun(Field, Arg) -> mochi@schema:argument(Field, Arg) end ), With_desc@1 = case Description@1 of {some, Desc@1} -> mochi@schema:field_description(With_args, Desc@1); none -> With_args end, apply_deprecation( With_desc@1, Is_deprecated@1, Deprecation_reason@1 ) end. -file("src/mochi/types.gleam", 810). ?DOC( " Generate an encoder function from a TypeBuilder\n" "\n" " The encoder uses the same extractors defined for each field,\n" " so you don't need to write the same field mappings twice.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " let user_builder = types.object(\"User\")\n" " |> types.id(\"id\", fn(u: User) { u.id })\n" " |> types.string(\"name\", fn(u: User) { u.name })\n" "\n" " let user_type = types.build(user_builder, decode_user)\n" " let user_encoder = types.encoder(user_builder)\n" "\n" " // user_encoder(User(\"1\", \"Alice\")) produces:\n" " // {\"id\": \"1\", \"name\": \"Alice\"}\n" " ```\n" " Build the TypeBuilder into an ObjectType using identity coerce instead of a\n" " decoder. This eliminates the encode/decode roundtrip — no Dict is built per\n" " object and no Dict lookups are done per field. The encoder is just\n" " `to_dynamic` (a BEAM no-op).\n" "\n" " Safe as long as the resolver returns values of type `a` and the extractors\n" " are defined for the same type `a`. Do not use when resolvers return\n" " pre-encoded Dicts.\n" ). -spec build_direct(type_builder(FRX)) -> {mochi@schema:object_type(), fun((FRX) -> gleam@dynamic:dynamic_())}. build_direct(Builder) -> Schema_fields = gleam@list:map( lists:reverse(erlang:element(4, Builder)), fun(F) -> to_field_def_direct(F) end ), Base_obj = mochi@schema:object(erlang:element(2, Builder)), With_desc = case erlang:element(3, Builder) of {some, D} -> mochi@schema:description(Base_obj, D); none -> Base_obj end, Object_type = gleam@list:fold( Schema_fields, With_desc, fun(Obj, Field) -> mochi@schema:field(Obj, Field) end ), {Object_type, fun gleam_stdlib:identity/1}. -file("src/mochi/types.gleam", 900). -spec encoder(type_builder(FSC)) -> fun((FSC) -> gleam@dynamic:dynamic_()). encoder(Builder) -> fun(Value) -> Field_pairs = gleam@list:filter_map( erlang:element(4, Builder), fun(F) -> case F of {type_field, Name, _, _, Extractor, _, _} -> {ok, {Name, Extractor(Value)}}; {type_field_with_args, _, _, _, _, _, _, _} -> {error, nil} end end ), gleam_stdlib:identity(maps:from_list(Field_pairs)) end. -file("src/mochi/types.gleam", 914). -spec to_field_def( type_field(FSE), fun((gleam@dynamic:dynamic_()) -> {ok, FSE} | {error, binary()}) ) -> mochi@schema:field_definition(). to_field_def(F, Decoder) -> case F of {type_field, Name, Description, Field_type, Extractor, Is_deprecated, Deprecation_reason} -> Resolver = fun(Info) -> case erlang:element(2, Info) of {some, Parent_dyn} -> gleam@result:map(Decoder(Parent_dyn), Extractor); none -> {error, <<"No parent value"/utf8>>} end end, Base = begin _pipe = mochi@schema:field_def(Name, Field_type), mochi@schema:resolver(_pipe, Resolver) end, With_desc = case Description of {some, Desc} -> mochi@schema:field_description(Base, Desc); none -> Base end, apply_deprecation(With_desc, Is_deprecated, Deprecation_reason); {type_field_with_args, Name@1, Description@1, Field_type@1, Args, Field_resolver, Is_deprecated@1, Deprecation_reason@1} -> Resolver@1 = fun(Info@1) -> case erlang:element(2, Info@1) of {some, Parent_dyn@1} -> gleam@result:'try'( Decoder(Parent_dyn@1), fun(Parent) -> Field_resolver( Parent, erlang:element(4, Info@1), erlang:element(5, Info@1) ) end ); none -> {error, <<"No parent value"/utf8>>} end end, Base@1 = begin _pipe@1 = mochi@schema:field_def(Name@1, Field_type@1), mochi@schema:resolver(_pipe@1, Resolver@1) end, With_args = gleam@list:fold( Args, Base@1, fun(Field, Arg) -> mochi@schema:argument(Field, Arg) end ), With_desc@1 = case Description@1 of {some, Desc@1} -> mochi@schema:field_description(With_args, Desc@1); none -> With_args end, apply_deprecation( With_desc@1, Is_deprecated@1, Deprecation_reason@1 ) end. -file("src/mochi/types.gleam", 729). ?DOC(" Build the TypeBuilder into an ObjectType with a decoder\n"). -spec build( type_builder(FRP), fun((gleam@dynamic:dynamic_()) -> {ok, FRP} | {error, binary()}) ) -> mochi@schema:object_type(). build(Builder, Decoder) -> Schema_fields = gleam@list:map( lists:reverse(erlang:element(4, Builder)), fun(F) -> to_field_def(F, Decoder) end ), Base_obj = mochi@schema:object(erlang:element(2, Builder)), With_desc = case erlang:element(3, Builder) of {some, D} -> mochi@schema:description(Base_obj, D); none -> Base_obj end, gleam@list:fold( Schema_fields, With_desc, fun(Obj, Field) -> mochi@schema:field(Obj, Field) end ). -file("src/mochi/types.gleam", 775). ?DOC( " Build the TypeBuilder into an ObjectType and auto-generated encoder\n" "\n" " This is the recommended way to build types - it generates both the\n" " schema type and an encoder function from the same field definitions,\n" " eliminating redundant code.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " pub type User {\n" " User(id: String, name: String, age: Int)\n" " }\n" "\n" " let #(user_type, user_encoder) = types.object(\"User\")\n" " |> types.id(\"id\", fn(u: User) { u.id })\n" " |> types.string(\"name\", fn(u: User) { u.name })\n" " |> types.int(\"age\", fn(u: User) { u.age })\n" " |> types.build_with_encoder(decode_user)\n" "\n" " // Use user_type in schema, user_encoder in resolvers\n" " query.query(\n" " name: \"user\",\n" " returns: schema.named_type(\"User\"),\n" " resolve: fn(_ctx) { Ok(User(\"1\", \"Alice\", 30)) },\n" " encode: user_encoder, // Auto-generated!\n" " )\n" " ```\n" ). -spec build_with_encoder( type_builder(FRT), fun((gleam@dynamic:dynamic_()) -> {ok, FRT} | {error, binary()}) ) -> {mochi@schema:object_type(), fun((FRT) -> gleam@dynamic:dynamic_())}. build_with_encoder(Builder, Decoder) -> Object_type = build(Builder, Decoder), Encoder_fn = encoder(Builder), {Object_type, Encoder_fn}. -file("src/mochi/types.gleam", 1004). ?DOC(" Create a new enum builder\n"). -spec enum_type(binary()) -> enum_builder(). enum_type(Name) -> {enum_builder, Name, none, []}. -file("src/mochi/types.gleam", 1009). ?DOC(" Add description to enum\n"). -spec enum_description(enum_builder(), binary()) -> enum_builder(). enum_description(Builder, Desc) -> {enum_builder, erlang:element(2, Builder), {some, Desc}, erlang:element(4, Builder)}. -file("src/mochi/types.gleam", 1014). ?DOC(" Add an enum value\n"). -spec value(enum_builder(), binary()) -> enum_builder(). value(Builder, Name) -> {enum_builder, erlang:element(2, Builder), erlang:element(3, Builder), [{enum_value, Name, none, false, none} | erlang:element(4, Builder)]}. -file("src/mochi/types.gleam", 1022). ?DOC(" Add an enum value with description\n"). -spec value_with_desc(enum_builder(), binary(), binary()) -> enum_builder(). value_with_desc(Builder, Name, Desc) -> {enum_builder, erlang:element(2, Builder), erlang:element(3, Builder), [{enum_value, Name, {some, Desc}, false, none} | erlang:element(4, Builder)]}. -file("src/mochi/types.gleam", 1034). ?DOC(" Add a deprecated enum value\n"). -spec deprecated_value(enum_builder(), binary()) -> enum_builder(). deprecated_value(Builder, Name) -> {enum_builder, erlang:element(2, Builder), erlang:element(3, Builder), [{enum_value, Name, none, true, none} | erlang:element(4, Builder)]}. -file("src/mochi/types.gleam", 1042). ?DOC(" Add a deprecated enum value with reason\n"). -spec deprecated_value_with_reason(enum_builder(), binary(), binary()) -> enum_builder(). deprecated_value_with_reason(Builder, Name, Reason) -> {enum_builder, erlang:element(2, Builder), erlang:element(3, Builder), [{enum_value, Name, none, true, {some, Reason}} | erlang:element(4, Builder)]}. -file("src/mochi/types.gleam", 1054). ?DOC(" Build the enum type\n"). -spec build_enum(enum_builder()) -> mochi@schema:enum_type(). build_enum(Builder) -> Enum_values = gleam@list:fold( lists:reverse(erlang:element(4, Builder)), maps:new(), fun(Acc, V) -> Value_def = {enum_value_definition, erlang:element(2, V), erlang:element(3, V), gleam_stdlib:identity(erlang:element(2, V)), erlang:element(4, V), erlang:element(5, V)}, gleam@dict:insert(Acc, erlang:element(2, V), Value_def) end ), {enum_type, erlang:element(2, Builder), erlang:element(3, Builder), Enum_values}. -file("src/mochi/types.gleam", 1085). ?DOC(" Create an enum mapping\n"). -spec enum_mapping(FSI, binary()) -> enum_mapping(FSI). enum_mapping(Gleam_value, Graphql_name) -> {enum_mapping, Gleam_value, Graphql_name, none}. -file("src/mochi/types.gleam", 1094). ?DOC(" Create an enum mapping with description\n"). -spec enum_mapping_with_desc(FSK, binary(), binary()) -> enum_mapping(FSK). enum_mapping_with_desc(Gleam_value, Graphql_name, Desc) -> {enum_mapping, Gleam_value, Graphql_name, {some, Desc}}. -file("src/mochi/types.gleam", 1137). ?DOC( " Build an enum type from mappings with bidirectional coercion functions\n" "\n" " Returns a tuple of:\n" " - The EnumType for schema registration\n" " - A function to convert Gleam value to GraphQL string\n" " - A function to convert GraphQL string to Gleam value\n" "\n" " ```gleam\n" " pub type Status {\n" " Active\n" " Inactive\n" " Pending\n" " }\n" "\n" " let #(enum_type, to_graphql, from_graphql) = types.enum_from_mappings(\n" " \"Status\",\n" " [\n" " types.enum_mapping(Active, \"ACTIVE\"),\n" " types.enum_mapping(Inactive, \"INACTIVE\"),\n" " types.enum_mapping_with_desc(Pending, \"PENDING\", \"Awaiting approval\"),\n" " ],\n" " )\n" "\n" " // Use in schema\n" " query.new()\n" " |> query.add_enum(enum_type)\n" "\n" " // Convert values\n" " to_graphql(Active) // -> \"ACTIVE\"\n" " from_graphql(\"ACTIVE\") // -> Ok(Active)\n" " ```\n" ). -spec enum_from_mappings(binary(), list(enum_mapping(FSM))) -> {mochi@schema:enum_type(), fun((FSM) -> binary()), fun((binary()) -> {ok, FSM} | {error, binary()})}. enum_from_mappings(Name, Mappings) -> Enum_values = gleam@list:fold( Mappings, maps:new(), fun(Acc, M) -> Value_def = {enum_value_definition, erlang:element(3, M), erlang:element(4, M), gleam_stdlib:identity(erlang:element(3, M)), false, none}, gleam@dict:insert(Acc, erlang:element(3, M), Value_def) end ), Enum_type = {enum_type, Name, none, Enum_values}, To_graphql = fun(Value) -> case gleam@list:find( Mappings, fun(M@1) -> gleam_stdlib:identity(erlang:element(2, M@1)) =:= gleam_stdlib:identity( Value ) end ) of {ok, M@2} -> erlang:element(3, M@2); {error, _} -> <<""/utf8>> end end, From_graphql = fun(Gql_name) -> case gleam@list:find( Mappings, fun(M@3) -> erlang:element(3, M@3) =:= Gql_name end ) of {ok, M@4} -> {ok, erlang:element(2, M@4)}; {error, _} -> {error, <<"Unknown enum value: "/utf8, Gql_name/binary>>} end end, {Enum_type, To_graphql, From_graphql}. -file("src/mochi/types.gleam", 1180). ?DOC(" Build an enum type from mappings with description\n"). -spec enum_from_mappings_with_desc(binary(), binary(), list(enum_mapping(FSR))) -> {mochi@schema:enum_type(), fun((FSR) -> binary()), fun((binary()) -> {ok, FSR} | {error, binary()})}. enum_from_mappings_with_desc(Name, Description, Mappings) -> {Enum_type, To_graphql, From_graphql} = enum_from_mappings(Name, Mappings), Enum_type_with_desc = {enum_type, erlang:element(2, Enum_type), {some, Description}, erlang:element(4, Enum_type)}, {Enum_type_with_desc, To_graphql, From_graphql}. -file("src/mochi/types.gleam", 1225). ?DOC( " Create a new input type builder\n" "\n" " ```gleam\n" " let create_user_input = types.input(\"CreateUserInput\")\n" " |> types.input_description(\"Input for creating a new user\")\n" " |> types.input_string(\"name\", \"User's full name\")\n" " |> types.input_string(\"email\", \"User's email address\")\n" " |> types.input_optional_int(\"age\", \"User's age\")\n" " |> types.build_input\n" " ```\n" ). -spec input(binary()) -> input_builder(). input(Name) -> {input_builder, Name, none, []}. -file("src/mochi/types.gleam", 1230). ?DOC(" Add description to input type\n"). -spec input_description(input_builder(), binary()) -> input_builder(). input_description(Builder, Desc) -> {input_builder, erlang:element(2, Builder), {some, Desc}, erlang:element(4, Builder)}. -file("src/mochi/types.gleam", 1316). ?DOC(" Add a field with custom type to input\n"). -spec input_field( input_builder(), binary(), mochi@schema:field_type(), binary() ) -> input_builder(). input_field(Builder, Name, Field_type, Desc) -> Field = {input_field, Name, {some, Desc}, Field_type, none}, {input_builder, erlang:element(2, Builder), erlang:element(3, Builder), [Field | erlang:element(4, Builder)]}. -file("src/mochi/types.gleam", 1235). ?DOC(" Add a required string field to input\n"). -spec input_string(input_builder(), binary(), binary()) -> input_builder(). input_string(Builder, Name, Desc) -> input_field( Builder, Name, mochi@schema:non_null(mochi@schema:string_type()), Desc ). -file("src/mochi/types.gleam", 1244). ?DOC(" Add a required int field to input\n"). -spec input_int(input_builder(), binary(), binary()) -> input_builder(). input_int(Builder, Name, Desc) -> input_field( Builder, Name, mochi@schema:non_null(mochi@schema:int_type()), Desc ). -file("src/mochi/types.gleam", 1253). ?DOC(" Add a required float field to input\n"). -spec input_float(input_builder(), binary(), binary()) -> input_builder(). input_float(Builder, Name, Desc) -> input_field( Builder, Name, mochi@schema:non_null(mochi@schema:float_type()), Desc ). -file("src/mochi/types.gleam", 1262). ?DOC(" Add a required bool field to input\n"). -spec input_bool(input_builder(), binary(), binary()) -> input_builder(). input_bool(Builder, Name, Desc) -> input_field( Builder, Name, mochi@schema:non_null(mochi@schema:boolean_type()), Desc ). -file("src/mochi/types.gleam", 1271). ?DOC(" Add a required ID field to input\n"). -spec input_id(input_builder(), binary(), binary()) -> input_builder(). input_id(Builder, Name, Desc) -> input_field( Builder, Name, mochi@schema:non_null(mochi@schema:id_type()), Desc ). -file("src/mochi/types.gleam", 1280). ?DOC(" Add an optional string field to input\n"). -spec input_optional_string(input_builder(), binary(), binary()) -> input_builder(). input_optional_string(Builder, Name, Desc) -> input_field(Builder, Name, mochi@schema:string_type(), Desc). -file("src/mochi/types.gleam", 1289). ?DOC(" Add an optional int field to input\n"). -spec input_optional_int(input_builder(), binary(), binary()) -> input_builder(). input_optional_int(Builder, Name, Desc) -> input_field(Builder, Name, mochi@schema:int_type(), Desc). -file("src/mochi/types.gleam", 1298). ?DOC(" Add an optional float field to input\n"). -spec input_optional_float(input_builder(), binary(), binary()) -> input_builder(). input_optional_float(Builder, Name, Desc) -> input_field(Builder, Name, mochi@schema:float_type(), Desc). -file("src/mochi/types.gleam", 1307). ?DOC(" Add an optional bool field to input\n"). -spec input_optional_bool(input_builder(), binary(), binary()) -> input_builder(). input_optional_bool(Builder, Name, Desc) -> input_field(Builder, Name, mochi@schema:boolean_type(), Desc). -file("src/mochi/types.gleam", 1333). ?DOC(" Add a field with custom type and default value to input\n"). -spec input_field_with_default( input_builder(), binary(), mochi@schema:field_type(), gleam@dynamic:dynamic_(), binary() ) -> input_builder(). input_field_with_default(Builder, Name, Field_type, Default, Desc) -> Field = {input_field, Name, {some, Desc}, Field_type, {some, Default}}, {input_builder, erlang:element(2, Builder), erlang:element(3, Builder), [Field | erlang:element(4, Builder)]}. -file("src/mochi/types.gleam", 1351). ?DOC(" Build the input type into a schema InputObjectType\n"). -spec build_input(input_builder()) -> mochi@schema:input_object_type(). build_input(Builder) -> Schema_fields = gleam@list:fold( lists:reverse(erlang:element(4, Builder)), maps:new(), fun(Acc, F) -> Field_def = {input_field_definition, erlang:element(2, F), erlang:element(3, F), erlang:element(4, F), erlang:element(5, F)}, gleam@dict:insert(Acc, erlang:element(2, F), Field_def) end ), {input_object_type, erlang:element(2, Builder), erlang:element(3, Builder), Schema_fields}.