-module(mochi@executor). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/mochi/executor.gleam"). -export([get_or_parse/2, execute_with_operation_name/6, execute/5, execute_query_with_variables/3, execute_query/2, execute_query_with_context/4, execute_query_debug_with_variables/3, execute_query_debug/2]). -export_type([deferred_patch/0, execution_result/0, execution_error/0, query_execution_context/0, field_context/0, debug_context/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. -type deferred_patch() :: {deferred_patch, list(binary()), gleam@option:option(gleam@dynamic:dynamic_()), list(execution_error()), gleam@option:option(binary())}. -type execution_result() :: {execution_result, gleam@option:option(gleam@dynamic:dynamic_()), list(execution_error()), list(deferred_patch())}. -type execution_error() :: {validation_error, binary(), list(binary()), gleam@option:option({integer(), integer()})} | {resolver_error, binary(), list(binary()), gleam@option:option({integer(), integer()})} | {type_error, binary(), list(binary()), gleam@option:option({integer(), integer()})} | {null_value_error, binary(), list(binary()), gleam@option:option({integer(), integer()})} | {rich_resolver_error, mochi@error:graph_q_l_error(), list(binary()), gleam@option:option({integer(), integer()})}. -type query_execution_context() :: {query_execution_context, mochi@schema:schema(), gleam@option:option(gleam@dynamic:dynamic_()), mochi@schema:execution_context(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()), gleam@dict:dict(binary(), mochi@internal@ast:fragment())}. -type field_context() :: {field_context, gleam@option:option(gleam@dynamic:dynamic_()), binary(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()), list(binary())}. -type debug_context() :: {debug_context, boolean(), integer(), integer()}. -file("src/mochi/executor.gleam", 102). -spec ok_result(gleam@dynamic:dynamic_()) -> execution_result(). ok_result(Data) -> {execution_result, {some, Data}, [], []}. -file("src/mochi/executor.gleam", 106). -spec error_result(execution_error()) -> execution_result(). error_result(Error) -> {execution_result, none, [Error], []}. -file("src/mochi/executor.gleam", 110). -spec validation_error(binary(), list(binary())) -> execution_result(). validation_error(Msg, Path) -> error_result({validation_error, Msg, Path, none}). -file("src/mochi/executor.gleam", 114). -spec validation_error_at( binary(), list(binary()), gleam@option:option({integer(), integer()}) ) -> execution_result(). validation_error_at(Msg, Path, Loc) -> error_result({validation_error, Msg, Path, Loc}). -file("src/mochi/executor.gleam", 122). -spec resolver_error(binary(), list(binary())) -> execution_result(). resolver_error(Msg, Path) -> error_result({resolver_error, Msg, Path, none}). -file("src/mochi/executor.gleam", 126). -spec resolver_error_at( binary(), list(binary()), gleam@option:option({integer(), integer()}) ) -> execution_result(). resolver_error_at(Msg, Path, Loc) -> error_result({resolver_error, Msg, Path, Loc}). -file("src/mochi/executor.gleam", 134). -spec type_error(binary(), list(binary())) -> execution_result(). type_error(Msg, Path) -> error_result({type_error, Msg, Path, none}). -file("src/mochi/executor.gleam", 138). -spec null_value_error(binary(), list(binary())) -> execution_result(). null_value_error(Msg, Path) -> error_result({null_value_error, Msg, Path, none}). -file("src/mochi/executor.gleam", 142). -spec null_value_error_at( binary(), list(binary()), gleam@option:option({integer(), integer()}) ) -> execution_result(). null_value_error_at(Msg, Path, Loc) -> error_result({null_value_error, Msg, Path, Loc}). -file("src/mochi/executor.gleam", 150). -spec rich_resolver_error_at( mochi@error:graph_q_l_error(), list(binary()), gleam@option:option({integer(), integer()}) ) -> execution_result(). rich_resolver_error_at(Err, Path, Loc) -> error_result({rich_resolver_error, Err, Path, Loc}). -file("src/mochi/executor.gleam", 239). ?DOC(" Get the operation name from a definition\n"). -spec get_operation_name_from_def(mochi@internal@ast:definition()) -> gleam@option:option(binary()). get_operation_name_from_def(Def) -> case Def of {operation_definition, {operation, _, Name, _, _, _}} -> Name; {operation_definition, {shorthand_query, _}} -> none; {fragment_definition, _} -> none end. -file("src/mochi/executor.gleam", 207). ?DOC(" Find an operation in the document by name\n"). -spec find_operation_by_name( mochi@internal@ast:document(), gleam@option:option(binary()) ) -> {ok, mochi@internal@ast:definition()} | {error, binary()}. find_operation_by_name(Document, Operation_name) -> Operations = begin _pipe = erlang:element(2, Document), gleam@list:filter(_pipe, fun(Def) -> case Def of {operation_definition, _} -> true; {fragment_definition, _} -> false end end) end, case {Operation_name, Operations} of {none, [Single]} -> {ok, Single}; {none, []} -> {error, <<"Document contains no operations"/utf8>>}; {none, _} -> {error, <<"Document contains multiple operations; operation name is required"/utf8>>}; {{some, Name}, Ops} -> _pipe@1 = Ops, _pipe@2 = gleam@list:find( _pipe@1, fun(Op) -> get_operation_name_from_def(Op) =:= {some, Name} end ), gleam@result:map_error( _pipe@2, fun(_) -> <<<<"Operation '"/utf8, Name/binary>>/binary, "' not found in document"/utf8>> end ) end. -file("src/mochi/executor.gleam", 247). -spec extract_fragments(mochi@internal@ast:document()) -> gleam@dict:dict(binary(), mochi@internal@ast:fragment()). extract_fragments(Document) -> _pipe = erlang:element(2, Document), _pipe@1 = gleam@list:filter_map(_pipe, fun(Def) -> case Def of {fragment_definition, Fragment} -> {ok, {erlang:element(2, Fragment), Fragment}}; {operation_definition, _} -> {error, nil} end end), maps:from_list(_pipe@1). -file("src/mochi/executor.gleam", 326). -spec get_variable_definitions(mochi@internal@ast:operation()) -> list(mochi@internal@ast:variable_definition()). get_variable_definitions(Operation) -> case Operation of {operation, _, _, Defs, _, _} -> Defs; {shorthand_query, _} -> [] end. -file("src/mochi/executor.gleam", 417). -spec is_non_null_ast_type(mochi@internal@ast:type()) -> boolean(). is_non_null_ast_type(T) -> case T of {non_null_type, _} -> true; _ -> false end. -file("src/mochi/executor.gleam", 425). ?DOC(" Convert an AST type to a schema FieldType for input coercion\n"). -spec ast_type_to_schema_type(mochi@internal@ast:type()) -> mochi@schema:field_type(). ast_type_to_schema_type(T) -> case T of {named_type, Name} -> {named, Name}; {list_type, Inner} -> {list, ast_type_to_schema_type(Inner)}; {non_null_type, Inner@1} -> {non_null, ast_type_to_schema_type(Inner@1)} end. -file("src/mochi/executor.gleam", 486). -spec check_named_type_value( gleam@dynamic:dynamic_(), binary(), mochi@schema:schema() ) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. check_named_type_value(Value, Type_name, Schema_def) -> case Type_name of <<"String"/utf8>> -> case gleam@dynamic@decode:run( Value, {decoder, fun gleam@dynamic@decode:decode_string/1} ) of {ok, _} -> {ok, Value}; {error, _} -> {error, <<"Expected String, got incompatible type"/utf8>>} end; <<"Int"/utf8>> -> case gleam@dynamic@decode:run( Value, {decoder, fun gleam@dynamic@decode:decode_int/1} ) of {ok, _} -> {ok, Value}; {error, _} -> {error, <<"Expected Int, got incompatible type"/utf8>>} end; <<"Float"/utf8>> -> case gleam@dynamic@decode:run( Value, {decoder, fun gleam@dynamic@decode:decode_float/1} ) of {ok, _} -> {ok, Value}; {error, _} -> case gleam@dynamic@decode:run( Value, {decoder, fun gleam@dynamic@decode:decode_int/1} ) of {ok, I} -> {ok, gleam_stdlib:identity(erlang:float(I))}; {error, _} -> {error, <<"Expected Float, got incompatible type"/utf8>>} end end; <<"Boolean"/utf8>> -> case gleam@dynamic@decode:run( Value, {decoder, fun gleam@dynamic@decode:decode_bool/1} ) of {ok, _} -> {ok, Value}; {error, _} -> {error, <<"Expected Boolean, got incompatible type"/utf8>>} end; <<"ID"/utf8>> -> case gleam@dynamic@decode:run( Value, {decoder, fun gleam@dynamic@decode:decode_string/1} ) of {ok, _} -> {ok, Value}; {error, _} -> case gleam@dynamic@decode:run( Value, {decoder, fun gleam@dynamic@decode:decode_int/1} ) of {ok, I@1} -> {ok, gleam_stdlib:identity( erlang:integer_to_binary(I@1) )}; {error, _} -> {error, <<"Expected ID (String or Int), got incompatible type"/utf8>>} end end; _ -> case gleam_stdlib:map_get(erlang:element(5, Schema_def), Type_name) of {ok, {enum_type_def, Enum_def}} -> case gleam@dynamic@decode:run( Value, {decoder, fun gleam@dynamic@decode:decode_string/1} ) of {ok, S} -> case gleam@dict:has_key( erlang:element(4, Enum_def), S ) of true -> {ok, Value}; false -> {error, <<<<<<"Value \""/utf8, S/binary>>/binary, "\" is not a valid value for enum "/utf8>>/binary, Type_name/binary>>} end; {error, _} -> {error, <<"Expected enum value for "/utf8, Type_name/binary>>} end; {ok, {input_object_type_def, _}} -> {ok, Value}; {ok, {scalar_type_def, _}} -> {ok, Value}; _ -> {ok, Value} end end. -file("src/mochi/executor.gleam", 555). -spec is_null_value(gleam@dynamic:dynamic_()) -> boolean(). is_null_value(Value) -> case Value =:= gleam_stdlib:identity(nil) of true -> true; false -> case gleam@dynamic@decode:run( Value, gleam@dynamic@decode:optional( {decoder, fun gleam@dynamic@decode:decode_dynamic/1} ) ) of {ok, none} -> true; _ -> false end end. -file("src/mochi/executor.gleam", 444). -spec check_value_against_schema_type( gleam@dynamic:dynamic_(), mochi@schema:field_type(), mochi@schema:schema() ) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. check_value_against_schema_type(Value, Field_type, Schema_def) -> case Field_type of {non_null, Inner} -> case is_null_value(Value) of true -> {error, <<"Expected non-null value but got null"/utf8>>}; false -> check_value_against_schema_type(Value, Inner, Schema_def) end; {list, Inner@1} -> case gleam@dynamic@decode:run( Value, gleam@dynamic@decode:list( {decoder, fun gleam@dynamic@decode:decode_dynamic/1} ) ) of {ok, Items} -> Results = gleam@list:index_map( Items, fun(Item, Idx) -> _pipe = check_value_against_schema_type( Item, Inner@1, Schema_def ), gleam@result:map_error( _pipe, fun(Msg) -> <<<<<<"At index "/utf8, (erlang:integer_to_binary(Idx))/binary>>/binary, ": "/utf8>>/binary, Msg/binary>> end ) end ), Errors = gleam@list:filter_map(Results, fun(R) -> case R of {ok, _} -> {error, nil}; {error, Msg@1} -> {ok, Msg@1} end end), case Errors of [] -> {ok, Value}; [First | _] -> {error, First} end; {error, _} -> check_value_against_schema_type(Value, Inner@1, Schema_def) end; {named, Type_name} -> check_named_type_value(Value, Type_name, Schema_def) end. -file("src/mochi/executor.gleam", 435). ?DOC( " Check that a Dynamic value is compatible with the declared variable type.\n" " Returns Ok with the (possibly coerced) value, or Error with a message.\n" ). -spec check_variable_type( gleam@dynamic:dynamic_(), mochi@internal@ast:type(), mochi@schema:schema() ) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. check_variable_type(Value, Declared_type, Schema_def) -> Schema_type = ast_type_to_schema_type(Declared_type), check_value_against_schema_type(Value, Schema_type, Schema_def). -file("src/mochi/executor.gleam", 337). ?DOC( " Coerce variable values against their declared types.\n" " Returns Error with a list of ExecutionErrors if any variable is invalid.\n" ). -spec coerce_variable_values( query_execution_context(), list(mochi@internal@ast:variable_definition()) ) -> {ok, gleam@dict:dict(binary(), gleam@dynamic:dynamic_())} | {error, list(execution_error())}. coerce_variable_values(Context, Var_defs) -> {Coerced, Errors} = gleam@list:fold( Var_defs, {erlang:element(5, Context), []}, fun(Acc, Var_def) -> {Values, Errs} = Acc, Var_name = erlang:element(2, Var_def), Declared_type = erlang:element(3, Var_def), Provided = gleam_stdlib:map_get(Values, Var_name), case {Provided, erlang:element(4, Var_def)} of {{ok, Value}, _} -> case {is_null_value(Value), is_non_null_ast_type(Declared_type)} of {true, false} -> {gleam@dict:insert(Values, Var_name, Value), Errs}; {_, _} -> case check_variable_type( Value, Declared_type, erlang:element(2, Context) ) of {ok, Coerced_value} -> {gleam@dict:insert( Values, Var_name, Coerced_value ), Errs}; {error, Msg} -> {Values, [{validation_error, <<<<<<"Variable \"$"/utf8, Var_name/binary>>/binary, "\": "/utf8>>/binary, Msg/binary>>, [], none} | Errs]} end end; {{error, _}, {some, Default_ast}} -> Default_value = mochi@input_coercion:coerce_argument_value( Default_ast, ast_type_to_schema_type(Declared_type), erlang:element(2, Context), maps:new(), [<<"$"/utf8, Var_name/binary>>] ), case Default_value of {ok, V} -> {gleam@dict:insert(Values, Var_name, V), Errs}; {error, _} -> {Values, Errs} end; {{error, _}, none} -> case is_non_null_ast_type(Declared_type) of true -> {Values, [{validation_error, <<<<"Variable \"$"/utf8, Var_name/binary>>/binary, "\" of required type is not provided"/utf8>>, [], none} | Errs]}; false -> {gleam@dict:insert( Values, Var_name, gleam_stdlib:identity(nil) ), Errs} end end end ), case Errors of [] -> {ok, Coerced}; _ -> {error, lists:reverse(Errors)} end. -file("src/mochi/executor.gleam", 568). -spec get_root_type(mochi@schema:schema(), mochi@internal@ast:operation()) -> gleam@option:option(mochi@schema:object_type()). get_root_type(Schema_def, Operation) -> case Operation of {operation, 'query', _, _, _, _} -> erlang:element(2, Schema_def); {operation, mutation, _, _, _, _} -> erlang:element(3, Schema_def); {operation, subscription, _, _, _, _} -> erlang:element(4, Schema_def); {shorthand_query, _} -> erlang:element(2, Schema_def) end. -file("src/mochi/executor.gleam", 581). -spec get_selection_set(mochi@internal@ast:operation()) -> mochi@internal@ast:selection_set(). get_selection_set(Operation) -> case Operation of {operation, _, _, _, _, Ss} -> Ss; {shorthand_query, Ss@1} -> Ss@1 end. -file("src/mochi/executor.gleam", 663). -spec extract_defer_label( mochi@internal@ast:directive(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()) ) -> gleam@option:option(binary()). extract_defer_label(Directive, Variables) -> _pipe = erlang:element(3, Directive), _pipe@1 = gleam@list:find( _pipe, fun(A) -> erlang:element(2, A) =:= <<"label"/utf8>> end ), _pipe@4 = gleam@result:'try'( _pipe@1, fun(A@1) -> case erlang:element(3, A@1) of {string_value, S} -> {ok, S}; {variable_value, Name} -> _pipe@2 = gleam_stdlib:map_get(Variables, Name), gleam@result:'try'( _pipe@2, fun(V) -> _pipe@3 = gleam@dynamic@decode:run( V, {decoder, fun gleam@dynamic@decode:decode_string/1} ), gleam@result:map_error(_pipe@3, fun(_) -> nil end) end ); _ -> {error, nil} end end ), gleam@option:from_result(_pipe@4). -file("src/mochi/executor.gleam", 787). -spec does_type_apply(mochi@schema:schema(), binary(), binary()) -> boolean(). does_type_apply(Schema_def, Object_type_name, Type_condition) -> case Object_type_name =:= Type_condition of true -> true; false -> Implements_interface = case gleam_stdlib:map_get( erlang:element(5, Schema_def), Object_type_name ) of {ok, {object_type_def, Obj}} -> gleam@list:any( erlang:element(5, Obj), fun(Iface) -> erlang:element(2, Iface) =:= Type_condition end ); _ -> false end, case Implements_interface of true -> true; false -> case gleam_stdlib:map_get( erlang:element(5, Schema_def), Type_condition ) of {ok, {union_type_def, Union_type}} -> gleam@list:any( erlang:element(4, Union_type), fun(T) -> erlang:element(2, T) =:= Object_type_name end ); _ -> false end end end. -file("src/mochi/executor.gleam", 913). -spec decode_bool_from_dynamic(gleam@dynamic:dynamic_()) -> gleam@option:option(boolean()). decode_bool_from_dynamic(Value) -> case gleam@dynamic@decode:run( Value, {decoder, fun gleam@dynamic@decode:decode_bool/1} ) of {ok, B} -> {some, B}; {error, _} -> none end. -file("src/mochi/executor.gleam", 898). ?DOC(" Evaluate a Value to a boolean, handling variables\n"). -spec eval_bool_value( mochi@internal@ast:value(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()) ) -> gleam@option:option(boolean()). eval_bool_value(Value, Variables) -> case Value of {boolean_value, B} -> {some, B}; {variable_value, Name} -> _pipe = gleam_stdlib:map_get(Variables, Name), _pipe@1 = gleam@result:map(_pipe, fun decode_bool_from_dynamic/1), gleam@result:unwrap(_pipe@1, none); _ -> none end. -file("src/mochi/executor.gleam", 880). ?DOC(" Get a boolean argument value from a specific directive\n"). -spec get_directive_bool_arg( list(mochi@internal@ast:directive()), binary(), binary(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()) ) -> gleam@option:option(boolean()). get_directive_bool_arg(Directives, Directive_name, Arg_name, Variables) -> _pipe = Directives, _pipe@1 = gleam@list:find( _pipe, fun(D) -> erlang:element(2, D) =:= Directive_name end ), _pipe@5 = gleam@result:map( _pipe@1, fun(Directive) -> _pipe@2 = erlang:element(3, Directive), _pipe@3 = gleam@list:find( _pipe@2, fun(Arg) -> erlang:element(2, Arg) =:= Arg_name end ), _pipe@4 = gleam@result:map( _pipe@3, fun(Arg@1) -> eval_bool_value(erlang:element(3, Arg@1), Variables) end ), gleam@result:unwrap(_pipe@4, none) end ), gleam@result:unwrap(_pipe@5, none). -file("src/mochi/executor.gleam", 683). -spec get_defer_info( mochi@internal@ast:selection(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()) ) -> gleam@option:option({gleam@option:option(binary()), boolean()}). get_defer_info(Selection, Variables) -> Directives = case Selection of {inline_fragment, Inline} -> erlang:element(3, Inline); {fragment_spread, Spread} -> erlang:element(3, Spread); {field_selection, _} -> [] end, case gleam@list:find( Directives, fun(D) -> erlang:element(2, D) =:= <<"defer"/utf8>> end ) of {error, _} -> none; {ok, Directive} -> Should_defer = begin _pipe = get_directive_bool_arg( [Directive], <<"defer"/utf8>>, <<"if"/utf8>>, Variables ), gleam@option:unwrap(_pipe, true) end, {some, {extract_defer_label(Directive, Variables), Should_defer}} end. -file("src/mochi/executor.gleam", 864). ?DOC(" Check if a field should be included based on @skip and @include directives\n"). -spec should_include_field( list(mochi@internal@ast:directive()), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()) ) -> boolean(). should_include_field(Directives, Variables) -> Skip_value = get_directive_bool_arg( Directives, <<"skip"/utf8>>, <<"if"/utf8>>, Variables ), Include_value = get_directive_bool_arg( Directives, <<"include"/utf8>>, <<"if"/utf8>>, Variables ), case {Skip_value, Include_value} of {{some, true}, _} -> false; {_, {some, false}} -> false; {_, _} -> true end. -file("src/mochi/executor.gleam", 968). ?DOC(" Skip built-in directives and call continuation for custom ones\n"). -spec skip_builtin_directive( binary(), gleam@dynamic:dynamic_(), fun(() -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}) ) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. skip_builtin_directive(Name, Value, Next) -> case Name of <<"skip"/utf8>> -> {ok, Value}; <<"include"/utf8>> -> {ok, Value}; <<"deprecated"/utf8>> -> {ok, Value}; <<"defer"/utf8>> -> {ok, Value}; _ -> Next() end. -file("src/mochi/executor.gleam", 980). ?DOC(" Get directive definition or pass through value if not found\n"). -spec with_directive_def( mochi@schema:schema(), binary(), gleam@dynamic:dynamic_(), fun((mochi@schema:directive_definition()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}) ) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. with_directive_def(Schema_def, Name, Value, Next) -> case gleam_stdlib:map_get(erlang:element(6, Schema_def), Name) of {ok, Directive_def} -> Next(Directive_def); {error, _} -> {ok, Value} end. -file("src/mochi/executor.gleam", 993). ?DOC(" Get directive handler or pass through value if none defined\n"). -spec with_directive_handler( mochi@schema:directive_definition(), gleam@dynamic:dynamic_(), fun((fun((gleam@dict:dict(binary(), gleam@dynamic:dynamic_()), gleam@dynamic:dynamic_()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()})) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}) ) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. with_directive_handler(Directive_def, Value, Next) -> case erlang:element(7, Directive_def) of {some, Handler} -> Next(Handler); none -> {ok, Value} end. -file("src/mochi/executor.gleam", 1014). -spec get_list_elements(gleam@dynamic:dynamic_()) -> gleam@option:option(list(gleam@dynamic:dynamic_())). get_list_elements(Value) -> case gleam@dynamic@decode:run( Value, gleam@dynamic@decode:list( {decoder, fun gleam@dynamic@decode:decode_dynamic/1} ) ) of {ok, Items} -> {some, Items}; {error, _} -> none end. -file("src/mochi/executor.gleam", 1021). -spec is_null(gleam@dynamic:dynamic_()) -> boolean(). is_null(Value) -> case gleam@dynamic@decode:run( Value, gleam@dynamic@decode:optional( {decoder, fun gleam@dynamic@decode:decode_dynamic/1} ) ) of {ok, none} -> true; _ -> false end. -file("src/mochi/executor.gleam", 1101). -spec require_field( mochi@schema:object_type(), binary(), list(binary()), gleam@option:option({integer(), integer()}), fun((mochi@schema:field_definition()) -> execution_result()) ) -> execution_result(). require_field(Object_type, Field_name, Path, Location, Next) -> case gleam_stdlib:map_get(erlang:element(4, Object_type), Field_name) of {ok, Field_def} -> Next(Field_def); {error, _} -> validation_error_at( <<<<<<<<"Field '"/utf8, Field_name/binary>>/binary, "' not found on type '"/utf8>>/binary, (erlang:element(2, Object_type))/binary>>/binary, "'"/utf8>>, Path, Location ) end. -file("src/mochi/executor.gleam", 1264). ?DOC(" Emit a SchemaEvent to the telemetry callback if one is configured.\n"). -spec emit_telemetry( mochi@schema:execution_context(), mochi@schema:schema_event() ) -> nil. emit_telemetry(Exec_context, Event) -> case erlang:element(6, Exec_context) of {some, Fn_} -> Fn_(Event); none -> nil end. -file("src/mochi/executor.gleam", 1276). ?DOC( " Execute a resolver through the middleware function if one is configured,\n" " otherwise call the resolver directly. Emits telemetry field events.\n" ). -spec execute_resolver_with_middleware( mochi@schema:execution_context(), mochi@schema:field_definition(), mochi@schema:resolver_info(), fun((mochi@schema:resolver_info()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}), binary() ) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. execute_resolver_with_middleware( Exec_context, Field_def, Resolver_info, Resolver, Parent_type_name ) -> Path = [], emit_telemetry( Exec_context, {schema_field_start, erlang:element(2, Field_def), Parent_type_name, Path} ), Start_ns = mochi_time_ffi:monotonic_time_ns(), Result = case erlang:element(4, Exec_context) of {some, Mw_fn} -> Mw_fn(Parent_type_name, Field_def, Resolver_info, Resolver); none -> Resolver(Resolver_info) end, Duration_ns = mochi_time_ffi:monotonic_time_ns() - Start_ns, emit_telemetry( Exec_context, {schema_field_end, erlang:element(2, Field_def), Parent_type_name, Path, begin _pipe = Result, gleam@result:is_ok(_pipe) end, Duration_ns} ), Result. -file("src/mochi/executor.gleam", 1428). ?DOC(" Check if a field type is a list type (unwrapping NonNull)\n"). -spec is_list_field_type(mochi@schema:field_type()) -> boolean(). is_list_field_type(Field_type) -> case Field_type of {list, _} -> true; {non_null, Inner} -> is_list_field_type(Inner); {named, _} -> false end. -file("src/mochi/executor.gleam", 1437). ?DOC(" Check if a field type is non-null at the outermost level\n"). -spec is_non_null_type(mochi@schema:field_type()) -> boolean(). is_non_null_type(Field_type) -> case Field_type of {non_null, _} -> true; _ -> false end. -file("src/mochi/executor.gleam", 1445). ?DOC(" Get the inner type of a list field type\n"). -spec get_list_inner_type(mochi@schema:field_type()) -> mochi@schema:field_type(). get_list_inner_type(Field_type) -> case Field_type of {list, Inner} -> Inner; {non_null, Inner@1} -> get_list_inner_type(Inner@1); _ -> Field_type end. -file("src/mochi/executor.gleam", 1688). ?DOC(" Require a type resolver function exists\n"). -spec require_type_resolver( gleam@option:option(fun((gleam@dynamic:dynamic_()) -> {ok, binary()} | {error, binary()})), list(binary()), fun((fun((gleam@dynamic:dynamic_()) -> {ok, binary()} | {error, binary()})) -> execution_result()) ) -> execution_result(). require_type_resolver(Resolve_type, Path, Next) -> case Resolve_type of {some, Resolver} -> Next(Resolver); none -> type_error( <<"Abstract type requires a resolve_type function"/utf8>>, Path ) end. -file("src/mochi/executor.gleam", 1700). ?DOC(" Require the type resolver successfully returns a type name\n"). -spec require_resolved_type( fun((gleam@dynamic:dynamic_()) -> {ok, binary()} | {error, binary()}), gleam@dynamic:dynamic_(), list(binary()), fun((binary()) -> execution_result()) ) -> execution_result(). require_resolved_type(Resolver, Value, Path, Next) -> case Resolver(Value) of {ok, Type_name} -> Next(Type_name); {error, Msg} -> resolver_error(<<"resolve_type failed: "/utf8, Msg/binary>>, Path) end. -file("src/mochi/executor.gleam", 1713). ?DOC(" Require the type name resolves to an object type in the schema\n"). -spec require_object_type( mochi@schema:schema(), binary(), list(binary()), fun((mochi@schema:object_type()) -> execution_result()) ) -> execution_result(). require_object_type(Schema_def, Type_name, Path, Next) -> case gleam_stdlib:map_get(erlang:element(5, Schema_def), Type_name) of {ok, {object_type_def, Concrete_type}} -> Next(Concrete_type); {ok, _} -> type_error( <<"resolve_type returned non-object type: "/utf8, Type_name/binary>>, Path ); {error, _} -> type_error( <<"resolve_type returned unknown type: "/utf8, Type_name/binary>>, Path ) end. -file("src/mochi/executor.gleam", 1749). -spec get_field_type_definition( mochi@schema:schema(), mochi@schema:field_type() ) -> {ok, mochi@schema:type_definition()} | {error, binary()}. get_field_type_definition(Schema_def, Field_type) -> case Field_type of {named, Name} -> case mochi@introspection:get_introspection_object_type(Name) of {some, Obj} -> {ok, {object_type_def, Obj}}; none -> _pipe = gleam_stdlib:map_get( erlang:element(5, Schema_def), Name ), gleam@result:map_error( _pipe, fun(_) -> <<<<"Type '"/utf8, Name/binary>>/binary, "' not found in schema"/utf8>> end ) end; {non_null, Inner} -> get_field_type_definition(Schema_def, Inner); {list, Inner@1} -> get_field_type_definition(Schema_def, Inner@1) end. -file("src/mochi/executor.gleam", 1775). ?DOC( " Coerce an AST value to Dynamic without type validation.\n" " Used for directive arguments where type checking is less critical.\n" ). -spec coerce_value_simple( mochi@internal@ast:value(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()) ) -> gleam@dynamic:dynamic_(). coerce_value_simple(Value, Variables) -> case Value of {int_value, I} -> gleam_stdlib:identity(I); {float_value, F} -> gleam_stdlib:identity(F); {string_value, S} -> gleam_stdlib:identity(S); {boolean_value, B} -> gleam_stdlib:identity(B); null_value -> gleam_stdlib:identity(nil); {enum_value, E} -> gleam_stdlib:identity(E); {variable_value, Name} -> _pipe = gleam_stdlib:map_get(Variables, Name), gleam@result:unwrap(_pipe, gleam_stdlib:identity(nil)); {list_value, Values} -> gleam_stdlib:identity( gleam@list:map( Values, fun(_capture) -> coerce_value_simple(_capture, Variables) end ) ); {object_value, Fields} -> gleam_stdlib:identity( gleam@list:fold( Fields, maps:new(), fun(Acc, F@1) -> gleam@dict:insert( Acc, erlang:element(2, F@1), coerce_value_simple( erlang:element(3, F@1), Variables ) ) end ) ) end. -file("src/mochi/executor.gleam", 1005). ?DOC(" Coerce directive arguments from AST to Dynamic values\n"). -spec coerce_directive_arguments( list(mochi@internal@ast:argument()), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()) ) -> gleam@dict:dict(binary(), gleam@dynamic:dynamic_()). coerce_directive_arguments(Args, Variables) -> gleam@list:fold( Args, maps:new(), fun(Acc, Arg) -> gleam@dict:insert( Acc, erlang:element(2, Arg), coerce_value_simple(erlang:element(3, Arg), Variables) ) end ). -file("src/mochi/executor.gleam", 952). ?DOC( " Apply a single directive handler to a value.\n" " Returns the transformed value or an error.\n" ). -spec apply_single_directive( mochi@schema:schema(), mochi@internal@ast:directive(), gleam@dynamic:dynamic_(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()), list(binary()) ) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. apply_single_directive(Schema_def, Directive, Value, Variables, _) -> skip_builtin_directive( erlang:element(2, Directive), Value, fun() -> with_directive_def( Schema_def, erlang:element(2, Directive), Value, fun(Directive_def) -> with_directive_handler( Directive_def, Value, fun(Handler) -> Args = coerce_directive_arguments( erlang:element(3, Directive), Variables ), Handler(Args, Value) end ) end ) end ). -file("src/mochi/executor.gleam", 928). ?DOC( " Apply custom directive handlers to a resolved field value.\n" " Directives are applied in order (left to right as they appear in the query).\n" " Built-in directives (@skip, @include, @deprecated) are skipped as they\n" " are handled specially elsewhere.\n" ). -spec apply_custom_directives( mochi@schema:schema(), list(mochi@internal@ast:directive()), gleam@dynamic:dynamic_(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()), list(binary()) ) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}. apply_custom_directives(Schema_def, Directives, Value, Variables, Path) -> gleam@list:fold(Directives, {ok, Value}, fun(Acc, Directive) -> case Acc of {error, Msg} -> {error, Msg}; {ok, Current_value} -> apply_single_directive( Schema_def, Directive, Current_value, Variables, Path ) end end). -file("src/mochi/executor.gleam", 1899). -spec decode_string_from_dynamic(gleam@dynamic:dynamic_()) -> gleam@option:option(binary()). decode_string_from_dynamic(Value) -> case gleam@dynamic@decode:run( Value, {decoder, fun gleam@dynamic@decode:decode_string/1} ) of {ok, S} -> {some, S}; {error, _} -> none end. -file("src/mochi/executor.gleam", 1885). -spec extract_string_value( mochi@internal@ast:value(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()) ) -> gleam@option:option(binary()). extract_string_value(Value, Variables) -> case Value of {string_value, S} -> {some, S}; {variable_value, Var_name} -> _pipe = gleam_stdlib:map_get(Variables, Var_name), _pipe@1 = gleam@result:map(_pipe, fun decode_string_from_dynamic/1), gleam@result:unwrap(_pipe@1, none); _ -> none end. -file("src/mochi/executor.gleam", 1875). -spec get_string_argument( list(mochi@internal@ast:argument()), binary(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()) ) -> gleam@option:option(binary()). get_string_argument(Args, Name, Variables) -> _pipe = gleam@list:find( Args, fun(Arg) -> erlang:element(2, Arg) =:= Name end ), _pipe@1 = gleam@result:map( _pipe, fun(Arg@1) -> extract_string_value(erlang:element(3, Arg@1), Variables) end ), gleam@result:unwrap(_pipe@1, none). -file("src/mochi/executor.gleam", 1909). -spec make_field(binary(), gleam@dynamic:dynamic_()) -> gleam@dynamic:dynamic_(). make_field(Name, Value) -> gleam_stdlib:identity(maps:from_list([{Name, Value}])). -file("src/mochi/executor.gleam", 1349). ?DOC(" Check for null values and handle non-null field constraints\n"). -spec with_non_null_check( gleam@dynamic:dynamic_(), mochi@schema:field_type(), binary(), list(binary()), gleam@option:option({integer(), integer()}), fun((gleam@dynamic:dynamic_()) -> execution_result()) ) -> execution_result(). with_non_null_check( Resolved, Field_type, Response_name, Field_path, Field_location, Next ) -> case {is_null(Resolved), is_non_null_type(Field_type)} of {true, true} -> null_value_error_at( <<<<"Cannot return null for non-null field '"/utf8, Response_name/binary>>/binary, "'"/utf8>>, Field_path, Field_location ); {true, false} -> ok_result(make_field(Response_name, gleam_stdlib:identity(nil))); {false, _} -> Next(Resolved) end. -file("src/mochi/executor.gleam", 1590). ?DOC(" Handle null errors in list results based on nullability\n"). -spec handle_list_null_error( mochi@schema:field_type(), binary(), list(execution_error()), list(deferred_patch()) ) -> execution_result(). handle_list_null_error(Field_type, Response_name, Errors, Deferred) -> case is_non_null_type(Field_type) of true -> {execution_result, none, Errors, Deferred}; false -> {execution_result, {some, make_field(Response_name, gleam_stdlib:identity(nil))}, Errors, Deferred} end. -file("src/mochi/executor.gleam", 1539). ?DOC(" Aggregate results from list item executions\n"). -spec aggregate_list_results( list(execution_result()), mochi@schema:field_type(), binary() ) -> execution_result(). aggregate_list_results(Results, Field_type, Response_name) -> {Data_acc, Errors_acc, Deferred_acc, Has_null_error} = gleam@list:fold( Results, {[], [], [], false}, fun(Acc, Result) -> {Data_list, Error_list, Deferred_list, Null_found} = Acc, New_data = case erlang:element(2, Result) of {some, D} -> [D | Data_list]; none -> Data_list end, New_null = Null_found orelse gleam@list:any( erlang:element(3, Result), fun(E) -> case E of {null_value_error, _, _, _} -> true; _ -> false end end ), {New_data, [erlang:element(3, Result) | Error_list], [erlang:element(4, Result) | Deferred_list], New_null} end ), Errors = begin _pipe = lists:reverse(Errors_acc), lists:append(_pipe) end, Deferred = begin _pipe@1 = lists:reverse(Deferred_acc), lists:append(_pipe@1) end, Data_list@1 = lists:reverse(Data_acc), case {Has_null_error, Errors} of {true, _} -> handle_list_null_error(Field_type, Response_name, Errors, Deferred); {false, []} -> {execution_result, {some, make_field( Response_name, gleam_stdlib:identity(Data_list@1) )}, [], Deferred}; {false, _} -> {execution_result, {some, make_field( Response_name, gleam_stdlib:identity(Data_list@1) )}, Errors, Deferred} end. -file("src/mochi/executor.gleam", 1608). ?DOC(" Wrap an execution result's data in a field\n"). -spec wrap_result_in_field(execution_result(), binary()) -> execution_result(). wrap_result_in_field(Result, Name) -> case erlang:element(2, Result) of {some, Data} -> {execution_result, {some, make_field(Name, Data)}, erlang:element(3, Result), erlang:element(4, Result)}; none -> Result end. -file("src/mochi/executor.gleam", 1410). ?DOC(" Handle null propagation from sub-selection results\n"). -spec handle_sub_selection_result( execution_result(), mochi@schema:field_type(), binary() ) -> execution_result(). handle_sub_selection_result(Sub_result, Field_type, Response_name) -> case {erlang:element(2, Sub_result), is_non_null_type(Field_type)} of {{some, _}, _} -> wrap_result_in_field(Sub_result, Response_name); {none, true} -> Sub_result; {none, false} -> {execution_result, {some, make_field(Response_name, gleam_stdlib:identity(nil))}, erlang:element(3, Sub_result), erlang:element(4, Sub_result)} end. -file("src/mochi/executor.gleam", 1728). -spec resolve_from_parent( gleam@option:option(gleam@dynamic:dynamic_()), binary(), binary(), list(binary()) ) -> execution_result(). resolve_from_parent(Parent, Field_name, Response_name, Field_path) -> _pipe = Parent, _pipe@1 = gleam@option:map( _pipe, fun(P) -> case gleam@dynamic@decode:run( P, gleam@dynamic@decode:dict( {decoder, fun gleam@dynamic@decode:decode_string/1}, {decoder, fun gleam@dynamic@decode:decode_dynamic/1} ) ) of {ok, D} -> case gleam_stdlib:map_get(D, Field_name) of {ok, Value} -> ok_result(make_field(Response_name, Value)); {error, _} -> ok_result( make_field( Response_name, gleam_stdlib:identity(nil) ) ) end; {error, _} -> ok_result( make_field(Response_name, gleam_stdlib:identity(nil)) ) end end ), gleam@option:unwrap( _pipe@1, resolver_error(<<"No resolver and no parent value"/utf8>>, Field_path) ). -file("src/mochi/executor.gleam", 1956). -spec get_cached(mochi@schema:schema(), binary()) -> {ok, mochi@internal@ast:document()} | {error, nil}. get_cached(Schema_def, Query) -> case erlang:element(7, Schema_def) of none -> {error, nil}; {some, Cache} -> mochi@document_cache:get(Cache, Query) end. -file("src/mochi/executor.gleam", 1966). -spec cache_put(mochi@schema:schema(), binary(), mochi@internal@ast:document()) -> nil. cache_put(Schema_def, Query, Doc) -> case erlang:element(7, Schema_def) of none -> nil; {some, Cache} -> mochi@document_cache:put(Cache, Query, Doc) end. -file("src/mochi/executor.gleam", 1942). -spec get_or_parse(mochi@schema:schema(), binary()) -> {ok, mochi@internal@ast:document()} | {error, mochi@parser:parse_error()}. get_or_parse(Schema_def, Query) -> case get_cached(Schema_def, Query) of {ok, Doc} -> {ok, Doc}; {error, _} -> gleam@result:map( mochi@parser:parse(Query), fun(Doc@1) -> cache_put(Schema_def, Query, Doc@1), Doc@1 end ) end. -file("src/mochi/executor.gleam", 2126). -spec log_step(debug_context(), binary()) -> nil. log_step(Debug, Msg) -> case erlang:element(2, Debug) of true -> gleam_stdlib:println( <<<<(gleam@string:repeat( <<" "/utf8>>, erlang:element(3, Debug) ))/binary, "📋 "/utf8>>/binary, Msg/binary>> ); false -> nil end. -file("src/mochi/executor.gleam", 2133). -spec log_info(debug_context(), binary()) -> nil. log_info(Debug, Msg) -> case erlang:element(2, Debug) of true -> gleam_stdlib:println( <<<<(gleam@string:repeat( <<" "/utf8>>, erlang:element(3, Debug) ))/binary, "🔍 "/utf8>>/binary, Msg/binary>> ); false -> nil end. -file("src/mochi/executor.gleam", 2140). -spec log_success(debug_context(), binary()) -> nil. log_success(Debug, Msg) -> case erlang:element(2, Debug) of true -> gleam_stdlib:println( <<<<(gleam@string:repeat( <<" "/utf8>>, erlang:element(3, Debug) ))/binary, "✅ "/utf8>>/binary, Msg/binary>> ); false -> nil end. -file("src/mochi/executor.gleam", 2147). -spec log_error(debug_context(), binary()) -> nil. log_error(Debug, Msg) -> case erlang:element(2, Debug) of true -> gleam_stdlib:println( <<<<(gleam@string:repeat( <<" "/utf8>>, erlang:element(3, Debug) ))/binary, "❌ "/utf8>>/binary, Msg/binary>> ); false -> nil end. -file("src/mochi/executor.gleam", 2154). -spec format_token(mochi@internal@lexer:token()) -> binary(). format_token(Token) -> case Token of {name, V} -> <<<<"\""/utf8, V/binary>>/binary, "\""/utf8>>; {int_value, V@1} -> erlang:integer_to_binary(V@1); {float_value, _} -> <<"Float"/utf8>>; {string_value, _} -> <<"String"/utf8>>; e_o_f -> <<"end of document"/utf8>>; bang -> <<"!"/utf8>>; dollar -> <<"$"/utf8>>; left_paren -> <<"("/utf8>>; right_paren -> <<")"/utf8>>; left_brace -> <<"{"/utf8>>; right_brace -> <<"}"/utf8>>; left_bracket -> <<"["/utf8>>; right_bracket -> <<"]"/utf8>>; colon -> <<":"/utf8>>; equals -> <<"="/utf8>>; spread -> <<"..."/utf8>>; pipe -> <<"|"/utf8>>; at -> <<"@"/utf8>>; amp -> <<"&"/utf8>>; 'query' -> <<"query"/utf8>>; mutation -> <<"mutation"/utf8>>; subscription -> <<"subscription"/utf8>>; fragment -> <<"fragment"/utf8>>; on -> <<"on"/utf8>>; true_keyword -> <<"true"/utf8>>; false_keyword -> <<"false"/utf8>>; null_keyword -> <<"null"/utf8>> end. -file("src/mochi/executor.gleam", 2186). -spec format_parse_error(mochi@parser:parse_error()) -> binary(). format_parse_error(Error) -> case Error of {lex_error, _} -> <<"Lexer error"/utf8>>; {unexpected_token, Expected, Got, _} -> <<<<<<"Expected "/utf8, Expected/binary>>/binary, ", got "/utf8>>/binary, (format_token(Got))/binary>>; {unexpected_e_o_f, Expected@1} -> <<"Unexpected end of document, expected "/utf8, Expected@1/binary>> end. -file("src/mochi/executor.gleam", 719). -spec execute_inline_fragment( query_execution_context(), mochi@internal@ast:inline_fragment_value(), mochi@schema:object_type(), field_context() ) -> execution_result(). execute_inline_fragment(Context, Inline, Object_type, Field_context) -> case erlang:element(2, Inline) of none -> execute_selection_set( Context, erlang:element(4, Inline), Object_type, Field_context ); {some, Type_name} -> case does_type_apply( erlang:element(2, Context), erlang:element(2, Object_type), Type_name ) of true -> execute_selection_set( Context, erlang:element(4, Inline), Object_type, Field_context ); false -> ok_result(gleam_stdlib:identity(maps:new())) end end. -file("src/mochi/executor.gleam", 592). -spec execute_selection_set( query_execution_context(), mochi@internal@ast:selection_set(), mochi@schema:object_type(), field_context() ) -> execution_result(). execute_selection_set(Context, Selection_set, Object_type, Field_context) -> {Data_dict, Errors_acc, Has_none, Deferred_acc} = gleam@list:fold( erlang:element(2, Selection_set), {maps:new(), [], false, []}, fun(Acc, Selection) -> {Data_map, Errors_list, None_found, Deferred_list} = Acc, case get_defer_info(Selection, erlang:element(5, Context)) of {some, {Label, true}} -> Result = execute_selection( Context, Selection, Object_type, Field_context ), Patch = {deferred_patch, erlang:element(5, Field_context), erlang:element(2, Result), erlang:element(3, Result), Label}, New_deferred = lists:append( Deferred_list, [Patch | erlang:element(4, Result)] ), {Data_map, Errors_list, None_found, New_deferred}; _ -> Result@1 = execute_selection( Context, Selection, Object_type, Field_context ), New_map = case erlang:element(2, Result@1) of {some, D} -> case gleam@dynamic@decode:run( D, gleam@dynamic@decode:dict( {decoder, fun gleam@dynamic@decode:decode_string/1}, {decoder, fun gleam@dynamic@decode:decode_dynamic/1} ) ) of {ok, Field_dict} -> maps:merge(Data_map, Field_dict); {error, _} -> Data_map end; none -> Data_map end, New_none = None_found orelse gleam@option:is_none( erlang:element(2, Result@1) ), New_deferred@1 = lists:append( Deferred_list, erlang:element(4, Result@1) ), {New_map, [erlang:element(3, Result@1) | Errors_list], New_none, New_deferred@1} end end ), Errors = begin _pipe = lists:reverse(Errors_acc), lists:append(_pipe) end, case {Has_none, gleam@dict:is_empty(Data_dict), Errors} of {true, _, _} -> {execution_result, none, Errors, Deferred_acc}; {false, true, []} -> {execution_result, {some, gleam_stdlib:identity(maps:new())}, [], Deferred_acc}; {false, true, _} -> {execution_result, none, Errors, Deferred_acc}; {false, false, _} -> {execution_result, {some, gleam_stdlib:identity(Data_dict)}, Errors, Deferred_acc} end. -file("src/mochi/executor.gleam", 703). -spec execute_selection( query_execution_context(), mochi@internal@ast:selection(), mochi@schema:object_type(), field_context() ) -> execution_result(). execute_selection(Context, Selection, Object_type, Field_context) -> case Selection of {field_selection, Field} -> execute_field(Context, Field, Object_type, Field_context); {fragment_spread, Spread} -> execute_fragment_spread(Context, Spread, Object_type, Field_context); {inline_fragment, Inline} -> execute_inline_fragment(Context, Inline, Object_type, Field_context) end. -file("src/mochi/executor.gleam", 269). -spec execute_operation( query_execution_context(), mochi@internal@ast:operation() ) -> execution_result(). execute_operation(Context, Operation) -> Root_type = get_root_type(erlang:element(2, Context), Operation), Selection_set = get_selection_set(Operation), Var_defs = get_variable_definitions(Operation), Operation_name = case Operation of {operation, _, Name, _, _, _} -> Name; {shorthand_query, _} -> none end, emit_telemetry( erlang:element(4, Context), {schema_operation_start, Operation_name} ), Exec_result = case coerce_variable_values(Context, Var_defs) of {error, Errors} -> {execution_result, none, Errors, []}; {ok, Coerced_variables} -> Context@1 = {query_execution_context, erlang:element(2, Context), erlang:element(3, Context), erlang:element(4, Context), Coerced_variables, erlang:element(6, Context)}, _pipe = Root_type, _pipe@1 = gleam@option:map( _pipe, fun(Obj_type) -> Field_ctx = {field_context, erlang:element(3, Context@1), <<"root"/utf8>>, maps:new(), []}, execute_selection_set( Context@1, Selection_set, Obj_type, Field_ctx ) end ), gleam@option:unwrap( _pipe@1, validation_error( <<"Schema does not define a root type for this operation"/utf8>>, [] ) ) end, emit_telemetry( erlang:element(4, Context), {schema_operation_end, Operation_name, gleam@list:is_empty(erlang:element(3, Exec_result)), erlang:length(erlang:element(3, Exec_result))} ), Exec_result. -file("src/mochi/executor.gleam", 258). -spec execute_definition( query_execution_context(), mochi@internal@ast:definition() ) -> execution_result(). execute_definition(Context, Definition) -> case Definition of {operation_definition, Operation} -> execute_operation(Context, Operation); {fragment_definition, _} -> erlang:error(#{gleam_error => panic, message => <<"unreachable: fragment definition reached execute_definition"/utf8>>, file => <>, module => <<"mochi/executor"/utf8>>, function => <<"execute_definition"/utf8>>, line => 265}) end. -file("src/mochi/executor.gleam", 181). ?DOC( " Execute with a specific operation name selected\n" " This is useful for documents containing multiple operations\n" ). -spec execute_with_operation_name( mochi@schema:schema(), mochi@internal@ast:document(), gleam@option:option(gleam@dynamic:dynamic_()), mochi@schema:execution_context(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()), gleam@option:option(binary()) ) -> execution_result(). execute_with_operation_name( Schema_def, Document, Root_value, Execution_context, Variable_values, Operation_name ) -> Fragments = extract_fragments(Document), Context = {query_execution_context, Schema_def, Root_value, Execution_context, Variable_values, Fragments}, case find_operation_by_name(Document, Operation_name) of {ok, Operation_def} -> execute_definition(Context, Operation_def); {error, Msg} -> validation_error(Msg, []) end. -file("src/mochi/executor.gleam", 162). -spec execute( mochi@schema:schema(), mochi@internal@ast:document(), gleam@option:option(gleam@dynamic:dynamic_()), mochi@schema:execution_context(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()) ) -> execution_result(). execute(Schema_def, Document, Root_value, Execution_context, Variable_values) -> execute_with_operation_name( Schema_def, Document, Root_value, Execution_context, Variable_values, none ). -file("src/mochi/executor.gleam", 751). -spec execute_fragment_spread( query_execution_context(), mochi@internal@ast:fragment_spread_value(), mochi@schema:object_type(), field_context() ) -> execution_result(). execute_fragment_spread(Context, Spread, Object_type, Field_context) -> case gleam_stdlib:map_get( erlang:element(6, Context), erlang:element(2, Spread) ) of {ok, Fragment} -> case does_type_apply( erlang:element(2, Context), erlang:element(2, Object_type), erlang:element(3, Fragment) ) of true -> execute_selection_set( Context, erlang:element(5, Fragment), Object_type, Field_context ); false -> ok_result(gleam_stdlib:identity(maps:new())) end; {error, _} -> validation_error( <<<<"Fragment '"/utf8, (erlang:element(2, Spread))/binary>>/binary, "' is not defined"/utf8>>, erlang:element(5, Field_context) ) end. -file("src/mochi/executor.gleam", 1661). -spec execute_abstract_type( query_execution_context(), mochi@internal@ast:selection_set(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()), list(binary()), gleam@dynamic:dynamic_(), gleam@option:option(fun((gleam@dynamic:dynamic_()) -> {ok, binary()} | {error, binary()})) ) -> execution_result(). execute_abstract_type( Context, Sub_selection_set, Field_args, Field_path, Resolved_value, Resolve_type ) -> require_type_resolver( Resolve_type, Field_path, fun(Resolver) -> require_resolved_type( Resolver, Resolved_value, Field_path, fun(Type_name) -> require_object_type( erlang:element(2, Context), Type_name, Field_path, fun(Concrete_type) -> Sub_ctx = {field_context, {some, Resolved_value}, <<""/utf8>>, Field_args, Field_path}, execute_selection_set( Context, Sub_selection_set, Concrete_type, Sub_ctx ) end ) end ) end ). -file("src/mochi/executor.gleam", 1618). -spec execute_sub_selection( query_execution_context(), mochi@internal@ast:selection_set(), mochi@schema:field_definition(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()), list(binary()), gleam@dynamic:dynamic_() ) -> execution_result(). execute_sub_selection( Context, Sub_selection_set, Field_def, Field_args, Field_path, Resolved_value ) -> case get_field_type_definition( erlang:element(2, Context), erlang:element(4, Field_def) ) of {ok, {object_type_def, Sub_type}} -> Sub_ctx = {field_context, {some, Resolved_value}, erlang:element(2, Field_def), Field_args, Field_path}, execute_selection_set(Context, Sub_selection_set, Sub_type, Sub_ctx); {ok, {interface_type_def, Iface}} -> execute_abstract_type( Context, Sub_selection_set, Field_args, Field_path, Resolved_value, erlang:element(5, Iface) ); {ok, {union_type_def, Union}} -> execute_abstract_type( Context, Sub_selection_set, Field_args, Field_path, Resolved_value, erlang:element(5, Union) ); {ok, _} -> type_error( <<"Cannot execute selection set on non-object type"/utf8>>, Field_path ); {error, Msg} -> type_error(Msg, Field_path) end. -file("src/mochi/executor.gleam", 1506). ?DOC(" Execute selection set on a single list item\n"). -spec execute_list_item( query_execution_context(), mochi@internal@ast:selection_set(), mochi@schema:field_definition(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()), gleam@dynamic:dynamic_(), integer(), list(binary()), boolean() ) -> execution_result(). execute_list_item( Context, Selection_set, Field_def, Field_args, Element, Index, Field_path, Items_non_null ) -> Item_path = lists:append(Field_path, [erlang:integer_to_binary(Index)]), case {is_null(Element), Items_non_null} of {true, true} -> null_value_error( <<"Cannot return null for non-null list item at index "/utf8, (erlang:integer_to_binary(Index))/binary>>, Item_path ); {true, false} -> ok_result(gleam_stdlib:identity(nil)); {false, _} -> execute_sub_selection( Context, Selection_set, Field_def, Field_args, Item_path, Element ) end. -file("src/mochi/executor.gleam", 1454). ?DOC(" Execute selection set on a list of items\n"). -spec execute_list_sub_selection( query_execution_context(), mochi@internal@ast:selection_set(), mochi@schema:field_definition(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()), binary(), list(binary()), gleam@dynamic:dynamic_() ) -> execution_result(). execute_list_sub_selection( Context, Sub_selection_set, Field_def, Field_args, Response_name, Field_path, Resolved_value ) -> case get_list_elements(Resolved_value) of {some, Elements} -> Inner_type = get_list_inner_type(erlang:element(4, Field_def)), Inner_field_def = {field_definition, erlang:element(2, Field_def), erlang:element(3, Field_def), Inner_type, erlang:element(5, Field_def), erlang:element(6, Field_def), erlang:element(7, Field_def), erlang:element(8, Field_def), erlang:element(9, Field_def), erlang:element(10, Field_def)}, Items_are_non_null = is_non_null_type(Inner_type), Results = gleam@list:index_map( Elements, fun(Element, Index) -> execute_list_item( Context, Sub_selection_set, Inner_field_def, Field_args, Element, Index, Field_path, Items_are_non_null ) end ), aggregate_list_results( Results, erlang:element(4, Field_def), Response_name ); none -> Sub_result = execute_sub_selection( Context, Sub_selection_set, Field_def, Field_args, Field_path, Resolved_value ), handle_sub_selection_result( Sub_result, erlang:element(4, Field_def), Response_name ) end. -file("src/mochi/executor.gleam", 1370). ?DOC(" Handle selection set execution for a field with a resolved value\n"). -spec handle_selection_set( query_execution_context(), mochi@internal@ast:selection_set(), mochi@schema:field_definition(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()), binary(), list(binary()), gleam@dynamic:dynamic_() ) -> execution_result(). handle_selection_set( Context, Sub_ss, Field_def, Field_args, Response_name, Field_path, Resolved ) -> case is_list_field_type(erlang:element(4, Field_def)) of true -> execute_list_sub_selection( Context, Sub_ss, Field_def, Field_args, Response_name, Field_path, Resolved ); false -> Sub_result = execute_sub_selection( Context, Sub_ss, Field_def, Field_args, Field_path, Resolved ), handle_sub_selection_result( Sub_result, erlang:element(4, Field_def), Response_name ) end. -file("src/mochi/executor.gleam", 1314). -spec handle_resolved_value( query_execution_context(), mochi@internal@ast:field(), mochi@schema:field_definition(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()), binary(), list(binary()), gleam@dynamic:dynamic_() ) -> execution_result(). handle_resolved_value( Context, Field, Field_def, Field_args, Response_name, Field_path, Resolved ) -> Field_location = gleam@option:map( erlang:element(7, Field), fun(Pos) -> {erlang:element(2, Pos), erlang:element(3, Pos)} end ), with_non_null_check( Resolved, erlang:element(4, Field_def), Response_name, Field_path, Field_location, fun(Resolved_value) -> case erlang:element(6, Field) of none -> ok_result(make_field(Response_name, Resolved_value)); {some, Sub_ss} -> handle_selection_set( Context, Sub_ss, Field_def, Field_args, Response_name, Field_path, Resolved_value ) end end ). -file("src/mochi/executor.gleam", 1123). -spec resolve_field( query_execution_context(), mochi@internal@ast:field(), mochi@schema:field_definition(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()), binary(), list(binary()), fun((mochi@schema:resolver_info()) -> {ok, gleam@dynamic:dynamic_()} | {error, binary()}), gleam@option:option(gleam@dynamic:dynamic_()), list(mochi@internal@ast:directive()) ) -> execution_result(). resolve_field( Context, Field, Field_def, Field_args, Response_name, Field_path, Resolver, Parent_value, Directives ) -> Field_location = gleam@option:map( erlang:element(7, Field), fun(Pos) -> {erlang:element(2, Pos), erlang:element(3, Pos)} end ), Resolver_info = {resolver_info, Parent_value, Field_args, mochi@args:from_dict(Field_args), erlang:element(4, Context), gleam_stdlib:identity(maps:new())}, Resolve_result = execute_resolver_with_middleware( erlang:element(4, Context), Field_def, Resolver_info, Resolver, Response_name ), case Resolve_result of {ok, Resolved} -> case apply_custom_directives( erlang:element(2, Context), Directives, Resolved, erlang:element(5, Context), Field_path ) of {ok, Transformed} -> handle_resolved_value( Context, Field, Field_def, Field_args, Response_name, Field_path, Transformed ); {error, Msg} -> resolver_error_at(Msg, Field_path, Field_location) end; {error, Msg@1} -> resolver_error_at(Msg@1, Field_path, Field_location) end. -file("src/mochi/executor.gleam", 1185). -spec resolve_rich_field( query_execution_context(), mochi@internal@ast:field(), mochi@schema:field_definition(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()), binary(), list(binary()), fun((mochi@schema:resolver_info()) -> {ok, gleam@dynamic:dynamic_()} | {error, {binary(), gleam@option:option(gleam@dict:dict(binary(), gleam@dynamic:dynamic_()))}}), gleam@option:option(gleam@dynamic:dynamic_()), list(mochi@internal@ast:directive()) ) -> execution_result(). resolve_rich_field( Context, Field, Field_def, Field_args, Response_name, Field_path, Rich_res, Parent_value, Directives ) -> Field_location = gleam@option:map( erlang:element(7, Field), fun(Pos) -> {erlang:element(2, Pos), erlang:element(3, Pos)} end ), Resolver_info = {resolver_info, Parent_value, Field_args, mochi@args:from_dict(Field_args), erlang:element(4, Context), gleam_stdlib:identity(maps:new())}, emit_telemetry( erlang:element(4, Context), {schema_field_start, erlang:element(2, Field_def), Response_name, Field_path} ), Start_ns = mochi_time_ffi:monotonic_time_ns(), Rich_result = Rich_res(Resolver_info), Duration_ns = mochi_time_ffi:monotonic_time_ns() - Start_ns, emit_telemetry( erlang:element(4, Context), {schema_field_end, erlang:element(2, Field_def), Response_name, Field_path, gleam@result:is_ok(Rich_result), Duration_ns} ), case Rich_result of {ok, Resolved} -> case apply_custom_directives( erlang:element(2, Context), Directives, Resolved, erlang:element(5, Context), Field_path ) of {ok, Transformed} -> handle_resolved_value( Context, Field, Field_def, Field_args, Response_name, Field_path, Transformed ); {error, Msg} -> resolver_error_at(Msg, Field_path, Field_location) end; {error, {Msg@1, Extensions}} -> rich_resolver_error_at( {graph_q_l_error, Msg@1, none, none, Extensions}, Field_path, Field_location ) end. -file("src/mochi/executor.gleam", 1028). -spec execute_regular_field( query_execution_context(), mochi@internal@ast:field(), mochi@schema:object_type(), field_context(), binary(), list(binary()) ) -> execution_result(). execute_regular_field( Context, Field, Object_type, Field_context, Response_name, Field_path ) -> Field_location = gleam@option:map( erlang:element(7, Field), fun(Pos) -> {erlang:element(2, Pos), erlang:element(3, Pos)} end ), require_field( Object_type, erlang:element(3, Field), Field_path, Field_location, fun(Field_def) -> case mochi@input_coercion:coerce_arguments( erlang:element(4, Field), erlang:element(5, Field_def), erlang:element(2, Context), erlang:element(5, Context), Field_path ) of {ok, Field_args} -> case {erlang:element(10, Field_def), erlang:element(6, Field_def)} of {{some, Rich_res}, _} -> resolve_rich_field( Context, Field, Field_def, Field_args, Response_name, Field_path, Rich_res, erlang:element(2, Field_context), erlang:element(5, Field) ); {none, {some, Resolver}} -> resolve_field( Context, Field, Field_def, Field_args, Response_name, Field_path, Resolver, erlang:element(2, Field_context), erlang:element(5, Field) ); {none, none} -> resolve_from_parent( erlang:element(2, Field_context), erlang:element(3, Field), Response_name, Field_path ) end; {error, Coercion_error} -> validation_error_at( mochi@input_coercion:format_error(Coercion_error), Field_path, Field_location ) end end ). -file("src/mochi/executor.gleam", 1803). -spec execute_introspection_schema( query_execution_context(), mochi@internal@ast:field(), binary() ) -> execution_result(). execute_introspection_schema(Context, Field, Response_name) -> Introspection_data = mochi@introspection:build_schema_introspection( erlang:element(2, Context) ), case erlang:element(6, Field) of none -> ok_result(make_field(Response_name, Introspection_data)); {some, Selection_set} -> Schema_type = mochi@introspection:get_introspection_schema_type(), Field_ctx = {field_context, {some, Introspection_data}, <<"__schema"/utf8>>, maps:new(), [Response_name]}, Result = execute_selection_set( Context, Selection_set, Schema_type, Field_ctx ), wrap_result_in_field(Result, Response_name) end. -file("src/mochi/executor.gleam", 1830). -spec execute_introspection_type( query_execution_context(), mochi@internal@ast:field(), list(binary()), binary() ) -> execution_result(). execute_introspection_type(Context, Field, Field_path, Response_name) -> _pipe = get_string_argument( erlang:element(4, Field), <<"name"/utf8>>, erlang:element(5, Context) ), _pipe@1 = gleam@option:map( _pipe, fun(Name) -> Introspection_data = mochi@introspection:build_type_introspection( erlang:element(2, Context), Name ), case is_null(Introspection_data) of true -> ok_result( make_field(Response_name, gleam_stdlib:identity(nil)) ); false -> case erlang:element(6, Field) of none -> ok_result( make_field(Response_name, Introspection_data) ); {some, Selection_set} -> Type_type = mochi@introspection:get_introspection_type_type( ), Field_ctx = {field_context, {some, Introspection_data}, <<"__type"/utf8>>, maps:new(), Field_path}, Result = execute_selection_set( Context, Selection_set, Type_type, Field_ctx ), wrap_result_in_field(Result, Response_name) end end end ), gleam@option:unwrap( _pipe@1, validation_error( <<"Missing required argument 'name' for __type"/utf8>>, Field_path ) ). -file("src/mochi/executor.gleam", 821). -spec execute_field( query_execution_context(), mochi@internal@ast:field(), mochi@schema:object_type(), field_context() ) -> execution_result(). execute_field(Context, Field, Object_type, Field_context) -> case should_include_field( erlang:element(5, Field), erlang:element(5, Context) ) of false -> ok_result(gleam_stdlib:identity(maps:new())); true -> Response_name = gleam@option:unwrap( erlang:element(2, Field), erlang:element(3, Field) ), Field_path = lists:append( erlang:element(5, Field_context), [Response_name] ), case erlang:element(3, Field) of <<"__typename"/utf8>> -> ok_result( make_field( Response_name, gleam_stdlib:identity( erlang:element(2, Object_type) ) ) ); <<"__schema"/utf8>> -> execute_introspection_schema(Context, Field, Response_name); <<"__type"/utf8>> -> execute_introspection_type( Context, Field, Field_path, Response_name ); _ -> execute_regular_field( Context, Field, Object_type, Field_context, Response_name, Field_path ) end end. -file("src/mochi/executor.gleam", 1924). -spec execute_query_with_variables( mochi@schema:schema(), binary(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()) ) -> execution_result(). execute_query_with_variables(Schema_def, Query, Variables) -> Ctx = mochi@schema:execution_context(gleam_stdlib:identity(maps:new())), case get_or_parse(Schema_def, Query) of {ok, Document} -> execute(Schema_def, Document, none, Ctx, Variables); {error, Error} -> Loc = case Error of {unexpected_token, _, _, Pos} -> {some, {erlang:element(2, Pos), erlang:element(3, Pos)}}; _ -> none end, validation_error_at( <<"Parse error: "/utf8, (format_parse_error(Error))/binary>>, [], Loc ) end. -file("src/mochi/executor.gleam", 1917). -spec execute_query(mochi@schema:schema(), binary()) -> execution_result(). execute_query(Schema_def, Query) -> execute_query_with_variables(Schema_def, Query, maps:new()). -file("src/mochi/executor.gleam", 1991). ?DOC( " Execute a query with a custom execution context (enables full telemetry).\n" "\n" " Use this function when you need telemetry for parsing and validation phases.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " let config = telemetry.with_handler(fn(event) { echo event })\n" " let ctx = schema.execution_context(user_data)\n" " |> schema.with_telemetry_fn(telemetry.to_schema_fn(config))\n" "\n" " let result = executor.execute_query_with_context(\n" " my_schema,\n" " \"{ users { name } }\",\n" " dict.new(),\n" " ctx,\n" " )\n" " ```\n" ). -spec execute_query_with_context( mochi@schema:schema(), binary(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()), mochi@schema:execution_context() ) -> execution_result(). execute_query_with_context(Schema_def, Query, Variables, Ctx) -> emit_telemetry(Ctx, schema_parse_start), Parse_start = mochi_time_ffi:monotonic_time_ns(), Parse_result = case get_cached(Schema_def, Query) of {ok, Doc} -> {ok, {Doc, true}}; {error, _} -> gleam@result:map( mochi@parser:parse(Query), fun(Doc@1) -> {Doc@1, false} end ) end, case Parse_result of {ok, {Document, Was_cached}} -> Parse_duration = mochi_time_ffi:monotonic_time_ns() - Parse_start, emit_telemetry(Ctx, {schema_parse_end, true, Parse_duration}), case Was_cached of true -> execute(Schema_def, Document, none, Ctx, Variables); false -> emit_telemetry(Ctx, schema_validation_start), Validation_start = mochi_time_ffi:monotonic_time_ns(), case mochi@validation:validate_located(Document, Schema_def) of {ok, _} -> Validation_duration = mochi_time_ffi:monotonic_time_ns( ) - Validation_start, emit_telemetry( Ctx, {schema_validation_end, true, 0, Validation_duration} ), cache_put(Schema_def, Query, Document), execute(Schema_def, Document, none, Ctx, Variables); {error, Validation_errors} -> Validation_duration@1 = mochi_time_ffi:monotonic_time_ns( ) - Validation_start, Error_count = erlang:length(Validation_errors), emit_telemetry( Ctx, {schema_validation_end, false, Error_count, Validation_duration@1} ), Errors = gleam@list:map( Validation_errors, fun(Le) -> {Err, Loc} = Le, {validation_error, mochi@validation:format_error(Err), [], Loc} end ), {execution_result, none, Errors, []} end end; {error, Error} -> Parse_duration@1 = mochi_time_ffi:monotonic_time_ns() - Parse_start, emit_telemetry(Ctx, {schema_parse_end, false, Parse_duration@1}), Loc@1 = case Error of {unexpected_token, _, _, Pos} -> {some, {erlang:element(2, Pos), erlang:element(3, Pos)}}; _ -> none end, validation_error_at( <<"Parse error: "/utf8, (format_parse_error(Error))/binary>>, [], Loc@1 ) end. -file("src/mochi/executor.gleam", 2081). -spec execute_query_debug_with_variables( mochi@schema:schema(), binary(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()) ) -> execution_result(). execute_query_debug_with_variables(Schema_def, Query, Variables) -> Debug = {debug_context, true, 0, 1}, log_step(Debug, <<"Starting GraphQL Query Execution"/utf8>>), log_info(Debug, <<"Query: "/utf8, Query/binary>>), log_step(Debug, <<"Parsing Query"/utf8>>), case mochi@parser:parse(Query) of {ok, Document} -> log_success(Debug, <<"Parse successful"/utf8>>), log_info( Debug, <<"Definitions: "/utf8, (erlang:integer_to_binary( erlang:length(erlang:element(2, Document)) ))/binary>> ), log_step(Debug, <<"Executing Query"/utf8>>), Result = execute_query_with_variables(Schema_def, Query, Variables), case erlang:element(2, Result) of {some, _} -> log_success(Debug, <<"Query executed successfully!"/utf8>>); none -> log_error( Debug, <<<<"Query execution failed: "/utf8, (erlang:integer_to_binary( erlang:length(erlang:element(3, Result)) ))/binary>>/binary, " errors"/utf8>> ) end, Result; {error, Error} -> log_error( Debug, <<"Parse failed: "/utf8, (format_parse_error(Error))/binary>> ), Loc = case Error of {unexpected_token, _, _, Pos} -> {some, {erlang:element(2, Pos), erlang:element(3, Pos)}}; _ -> none end, validation_error_at( <<"Parse error: "/utf8, (format_parse_error(Error))/binary>>, [], Loc ) end. -file("src/mochi/executor.gleam", 2074). -spec execute_query_debug(mochi@schema:schema(), binary()) -> execution_result(). execute_query_debug(Schema_def, Query) -> execute_query_debug_with_variables(Schema_def, Query, maps:new()).