graphql 1.9.5 → 1.13.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of graphql might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/lib/generators/graphql/core.rb +21 -9
- data/lib/generators/graphql/enum_generator.rb +4 -10
- data/lib/generators/graphql/field_extractor.rb +31 -0
- data/lib/generators/graphql/input_generator.rb +50 -0
- data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
- data/lib/generators/graphql/install/templates/base_mutation.erb +10 -0
- data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +2 -0
- data/lib/generators/graphql/install_generator.rb +48 -8
- data/lib/generators/graphql/interface_generator.rb +7 -7
- data/lib/generators/graphql/loader_generator.rb +1 -0
- data/lib/generators/graphql/mutation_create_generator.rb +22 -0
- data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
- data/lib/generators/graphql/mutation_generator.rb +6 -30
- data/lib/generators/graphql/mutation_update_generator.rb +22 -0
- data/lib/generators/graphql/object_generator.rb +28 -12
- data/lib/generators/graphql/orm_mutations_base.rb +40 -0
- data/lib/generators/graphql/relay.rb +63 -0
- data/lib/generators/graphql/relay_generator.rb +21 -0
- data/lib/generators/graphql/scalar_generator.rb +4 -2
- data/lib/generators/graphql/templates/base_argument.erb +6 -0
- data/lib/generators/graphql/templates/base_connection.erb +8 -0
- data/lib/generators/graphql/templates/base_edge.erb +8 -0
- data/lib/generators/graphql/templates/base_enum.erb +2 -0
- data/lib/generators/graphql/templates/base_field.erb +7 -0
- data/lib/generators/graphql/templates/base_input_object.erb +3 -0
- data/lib/generators/graphql/templates/base_interface.erb +4 -0
- data/lib/generators/graphql/templates/base_object.erb +3 -0
- data/lib/generators/graphql/templates/base_scalar.erb +2 -0
- data/lib/generators/graphql/templates/base_union.erb +2 -0
- data/lib/generators/graphql/templates/enum.erb +7 -1
- data/lib/generators/graphql/templates/graphql_controller.erb +21 -12
- data/lib/generators/graphql/templates/input.erb +9 -0
- data/lib/generators/graphql/templates/interface.erb +6 -2
- data/lib/generators/graphql/templates/loader.erb +2 -0
- data/lib/generators/graphql/templates/mutation.erb +3 -1
- data/lib/generators/graphql/templates/mutation_create.erb +20 -0
- data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
- data/lib/generators/graphql/templates/mutation_update.erb +21 -0
- data/lib/generators/graphql/templates/node_type.erb +9 -0
- data/lib/generators/graphql/templates/object.erb +7 -3
- data/lib/generators/graphql/templates/query_type.erb +3 -3
- data/lib/generators/graphql/templates/scalar.erb +5 -1
- data/lib/generators/graphql/templates/schema.erb +23 -28
- data/lib/generators/graphql/templates/union.erb +6 -2
- data/lib/generators/graphql/type_generator.rb +47 -10
- data/lib/generators/graphql/union_generator.rb +5 -5
- data/lib/graphql/analysis/analyze_query.rb +7 -0
- data/lib/graphql/analysis/ast/analyzer.rb +34 -12
- data/lib/graphql/analysis/ast/field_usage.rb +29 -2
- data/lib/graphql/analysis/ast/max_query_complexity.rb +3 -3
- data/lib/graphql/analysis/ast/max_query_depth.rb +7 -3
- data/lib/graphql/analysis/ast/query_complexity.rb +179 -64
- data/lib/graphql/analysis/ast/query_depth.rb +16 -26
- data/lib/graphql/analysis/ast/visitor.rb +46 -32
- data/lib/graphql/analysis/ast.rb +23 -14
- data/lib/graphql/analysis/query_depth.rb +4 -17
- data/lib/graphql/argument.rb +16 -38
- data/lib/graphql/backtrace/inspect_result.rb +0 -1
- data/lib/graphql/backtrace/legacy_tracer.rb +56 -0
- data/lib/graphql/backtrace/table.rb +44 -5
- data/lib/graphql/backtrace/traced_error.rb +0 -1
- data/lib/graphql/backtrace/tracer.rb +40 -9
- data/lib/graphql/backtrace.rb +28 -19
- data/lib/graphql/backwards_compatibility.rb +2 -1
- data/lib/graphql/base_type.rb +11 -5
- data/lib/graphql/boolean_type.rb +1 -1
- data/lib/graphql/coercion_error.rb +8 -0
- data/lib/graphql/compatibility/execution_specification/specification_schema.rb +2 -2
- data/lib/graphql/compatibility/execution_specification.rb +1 -0
- data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +1 -1
- data/lib/graphql/compatibility/lazy_execution_specification.rb +2 -0
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +5 -9
- data/lib/graphql/compatibility/query_parser_specification.rb +2 -0
- data/lib/graphql/compatibility/schema_parser_specification.rb +2 -0
- data/lib/graphql/dataloader/null_dataloader.rb +22 -0
- data/lib/graphql/dataloader/request.rb +19 -0
- data/lib/graphql/dataloader/request_all.rb +19 -0
- data/lib/graphql/dataloader/source.rb +155 -0
- data/lib/graphql/dataloader.rb +308 -0
- data/lib/graphql/date_encoding_error.rb +16 -0
- data/lib/graphql/define/assign_enum_value.rb +1 -1
- data/lib/graphql/define/assign_global_id_field.rb +2 -2
- data/lib/graphql/define/assign_object_field.rb +3 -3
- data/lib/graphql/define/defined_object_proxy.rb +3 -0
- data/lib/graphql/define/instance_definable.rb +65 -110
- data/lib/graphql/define/type_definer.rb +5 -5
- data/lib/graphql/deprecated_dsl.rb +18 -5
- data/lib/graphql/deprecation.rb +9 -0
- data/lib/graphql/directive/deprecated_directive.rb +1 -12
- data/lib/graphql/directive/include_directive.rb +1 -1
- data/lib/graphql/directive/skip_directive.rb +1 -1
- data/lib/graphql/directive.rb +9 -6
- data/lib/graphql/enum_type.rb +14 -74
- data/lib/graphql/execution/directive_checks.rb +2 -2
- data/lib/graphql/execution/errors.rb +163 -0
- data/lib/graphql/execution/execute.rb +10 -3
- data/lib/graphql/execution/instrumentation.rb +1 -1
- data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
- data/lib/graphql/execution/interpreter/arguments.rb +88 -0
- data/lib/graphql/execution/interpreter/arguments_cache.rb +105 -0
- data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
- data/lib/graphql/execution/interpreter/resolve.rb +37 -25
- data/lib/graphql/execution/interpreter/runtime.rb +737 -376
- data/lib/graphql/execution/interpreter.rb +42 -19
- data/lib/graphql/execution/lazy/lazy_method_map.rb +4 -0
- data/lib/graphql/execution/lazy.rb +5 -1
- data/lib/graphql/execution/lookahead.rb +39 -114
- data/lib/graphql/execution/multiplex.rb +58 -29
- data/lib/graphql/execution.rb +1 -0
- data/lib/graphql/execution_error.rb +3 -2
- data/lib/graphql/field.rb +15 -119
- data/lib/graphql/filter.rb +1 -1
- data/lib/graphql/float_type.rb +1 -1
- data/lib/graphql/function.rb +6 -31
- data/lib/graphql/id_type.rb +1 -1
- data/lib/graphql/input_object_type.rb +11 -26
- data/lib/graphql/int_type.rb +1 -1
- data/lib/graphql/integer_decoding_error.rb +17 -0
- data/lib/graphql/integer_encoding_error.rb +18 -2
- data/lib/graphql/interface_type.rb +10 -24
- data/lib/graphql/internal_representation/document.rb +2 -2
- data/lib/graphql/internal_representation/rewrite.rb +1 -1
- data/lib/graphql/internal_representation/scope.rb +2 -2
- data/lib/graphql/internal_representation/visit.rb +2 -2
- data/lib/graphql/introspection/base_object.rb +2 -5
- data/lib/graphql/introspection/directive_location_enum.rb +2 -2
- data/lib/graphql/introspection/directive_type.rb +12 -6
- data/lib/graphql/introspection/entry_points.rb +9 -8
- data/lib/graphql/introspection/enum_value_type.rb +2 -2
- data/lib/graphql/introspection/field_type.rb +9 -5
- data/lib/graphql/introspection/input_value_type.rb +41 -11
- data/lib/graphql/introspection/introspection_query.rb +6 -92
- data/lib/graphql/introspection/schema_type.rb +13 -12
- data/lib/graphql/introspection/type_type.rb +27 -17
- data/lib/graphql/introspection.rb +99 -0
- data/lib/graphql/invalid_null_error.rb +18 -0
- data/lib/graphql/language/block_string.rb +22 -7
- data/lib/graphql/language/cache.rb +37 -0
- data/lib/graphql/language/definition_slice.rb +21 -10
- data/lib/graphql/language/document_from_schema_definition.rb +126 -67
- data/lib/graphql/language/lexer.rb +180 -141
- data/lib/graphql/language/lexer.rl +75 -51
- data/lib/graphql/language/nodes.rb +92 -108
- data/lib/graphql/language/parser.rb +933 -897
- data/lib/graphql/language/parser.y +129 -103
- data/lib/graphql/language/printer.rb +11 -2
- data/lib/graphql/language/sanitized_printer.rb +222 -0
- data/lib/graphql/language/token.rb +1 -1
- data/lib/graphql/language/visitor.rb +11 -8
- data/lib/graphql/language.rb +3 -1
- data/lib/graphql/name_validator.rb +2 -7
- data/lib/graphql/non_null_type.rb +0 -10
- data/lib/graphql/object_type.rb +47 -58
- data/lib/graphql/pagination/active_record_relation_connection.rb +85 -0
- data/lib/graphql/pagination/array_connection.rb +77 -0
- data/lib/graphql/pagination/connection.rb +226 -0
- data/lib/graphql/pagination/connections.rb +160 -0
- data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
- data/lib/graphql/pagination/relation_connection.rb +226 -0
- data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
- data/lib/graphql/pagination.rb +6 -0
- data/lib/graphql/parse_error.rb +0 -1
- data/lib/graphql/query/arguments.rb +29 -19
- data/lib/graphql/query/arguments_cache.rb +1 -2
- data/lib/graphql/query/context.rb +81 -14
- data/lib/graphql/query/executor.rb +0 -1
- data/lib/graphql/query/fingerprint.rb +26 -0
- data/lib/graphql/query/input_validation_result.rb +32 -6
- data/lib/graphql/query/literal_input.rb +31 -10
- data/lib/graphql/query/null_context.rb +28 -8
- data/lib/graphql/query/serial_execution/field_resolution.rb +1 -1
- data/lib/graphql/query/serial_execution.rb +1 -0
- data/lib/graphql/query/validation_pipeline.rb +6 -4
- data/lib/graphql/query/variable_validation_error.rb +3 -3
- data/lib/graphql/query/variables.rb +51 -9
- data/lib/graphql/query.rb +97 -23
- data/lib/graphql/railtie.rb +9 -1
- data/lib/graphql/rake_task/validate.rb +3 -0
- data/lib/graphql/rake_task.rb +12 -9
- data/lib/graphql/relay/array_connection.rb +11 -13
- data/lib/graphql/relay/base_connection.rb +33 -16
- data/lib/graphql/relay/connection_instrumentation.rb +4 -4
- data/lib/graphql/relay/connection_type.rb +18 -4
- data/lib/graphql/relay/edge_type.rb +1 -0
- data/lib/graphql/relay/edges_instrumentation.rb +1 -2
- data/lib/graphql/relay/global_id_resolve.rb +1 -2
- data/lib/graphql/relay/mutation.rb +3 -87
- data/lib/graphql/relay/node.rb +5 -2
- data/lib/graphql/relay/page_info.rb +1 -1
- data/lib/graphql/relay/range_add.rb +27 -9
- data/lib/graphql/relay/relation_connection.rb +17 -15
- data/lib/graphql/relay/type_extensions.rb +2 -0
- data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
- data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
- data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
- data/lib/graphql/rubocop.rb +4 -0
- data/lib/graphql/scalar_type.rb +18 -62
- data/lib/graphql/schema/addition.rb +247 -0
- data/lib/graphql/schema/argument.rb +289 -11
- data/lib/graphql/schema/base_64_bp.rb +3 -2
- data/lib/graphql/schema/base_64_encoder.rb +2 -0
- data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +1 -1
- data/lib/graphql/schema/build_from_definition/resolve_map.rb +13 -5
- data/lib/graphql/schema/build_from_definition.rb +323 -203
- data/lib/graphql/schema/built_in_types.rb +5 -5
- data/lib/graphql/schema/default_type_error.rb +2 -0
- data/lib/graphql/schema/directive/deprecated.rb +18 -0
- data/lib/graphql/schema/directive/feature.rb +2 -2
- data/lib/graphql/schema/directive/flagged.rb +57 -0
- data/lib/graphql/schema/directive/include.rb +2 -2
- data/lib/graphql/schema/directive/skip.rb +2 -2
- data/lib/graphql/schema/directive/transform.rb +14 -2
- data/lib/graphql/schema/directive.rb +136 -6
- data/lib/graphql/schema/enum.rb +121 -12
- data/lib/graphql/schema/enum_value.rb +23 -6
- data/lib/graphql/schema/field/connection_extension.rb +46 -20
- data/lib/graphql/schema/field/scope_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +515 -191
- data/lib/graphql/schema/field_extension.rb +89 -2
- data/lib/graphql/schema/find_inherited_value.rb +36 -0
- data/lib/graphql/schema/finder.rb +16 -14
- data/lib/graphql/schema/input_object.rb +178 -34
- data/lib/graphql/schema/interface.rb +35 -25
- data/lib/graphql/schema/introspection_system.rb +111 -35
- data/lib/graphql/schema/late_bound_type.rb +3 -2
- data/lib/graphql/schema/list.rb +65 -1
- data/lib/graphql/schema/loader.rb +147 -97
- data/lib/graphql/schema/member/accepts_definition.rb +15 -3
- data/lib/graphql/schema/member/base_dsl_methods.rb +40 -45
- data/lib/graphql/schema/member/build_type.rb +19 -8
- data/lib/graphql/schema/member/cached_graphql_definition.rb +34 -2
- data/lib/graphql/schema/member/has_arguments.rb +212 -22
- data/lib/graphql/schema/member/has_ast_node.rb +20 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
- data/lib/graphql/schema/member/has_directives.rb +98 -0
- data/lib/graphql/schema/member/has_fields.rb +113 -28
- data/lib/graphql/schema/member/has_interfaces.rb +100 -0
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
- data/lib/graphql/schema/member/has_validators.rb +31 -0
- data/lib/graphql/schema/member/instrumentation.rb +6 -2
- data/lib/graphql/schema/member/relay_shortcuts.rb +2 -2
- data/lib/graphql/schema/member/type_system_helpers.rb +3 -3
- data/lib/graphql/schema/member/validates_input.rb +33 -0
- data/lib/graphql/schema/member.rb +11 -0
- data/lib/graphql/schema/middleware_chain.rb +1 -1
- data/lib/graphql/schema/mutation.rb +5 -1
- data/lib/graphql/schema/non_null.rb +37 -1
- data/lib/graphql/schema/object.rb +52 -37
- data/lib/graphql/schema/possible_types.rb +12 -7
- data/lib/graphql/schema/printer.rb +17 -34
- data/lib/graphql/schema/relay_classic_mutation.rb +51 -7
- data/lib/graphql/schema/resolver/has_payload_type.rb +36 -5
- data/lib/graphql/schema/resolver.rb +159 -59
- data/lib/graphql/schema/scalar.rb +43 -3
- data/lib/graphql/schema/subscription.rb +83 -25
- data/lib/graphql/schema/timeout.rb +123 -0
- data/lib/graphql/schema/timeout_middleware.rb +6 -3
- data/lib/graphql/schema/traversal.rb +2 -2
- data/lib/graphql/schema/type_expression.rb +21 -13
- data/lib/graphql/schema/type_membership.rb +48 -0
- data/lib/graphql/schema/union.rb +67 -6
- data/lib/graphql/schema/unique_within_type.rb +1 -2
- data/lib/graphql/schema/validation.rb +30 -8
- data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
- data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
- data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
- data/lib/graphql/schema/validator/format_validator.rb +48 -0
- data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
- data/lib/graphql/schema/validator/length_validator.rb +59 -0
- data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
- data/lib/graphql/schema/validator/required_validator.rb +82 -0
- data/lib/graphql/schema/validator.rb +171 -0
- data/lib/graphql/schema/warden.rb +263 -30
- data/lib/graphql/schema/wrapper.rb +1 -1
- data/lib/graphql/schema.rb +1016 -256
- data/lib/graphql/static_validation/all_rules.rb +2 -0
- data/lib/graphql/static_validation/base_visitor.rb +17 -10
- data/lib/graphql/static_validation/definition_dependencies.rb +21 -13
- data/lib/graphql/static_validation/error.rb +3 -1
- data/lib/graphql/static_validation/literal_validator.rb +52 -27
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +46 -79
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +23 -6
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +35 -26
- data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -1
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +2 -2
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +4 -4
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +5 -5
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +105 -55
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
- data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
- data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
- data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
- data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +5 -3
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +9 -10
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +12 -13
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +19 -14
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +5 -3
- data/lib/graphql/static_validation/type_stack.rb +2 -2
- data/lib/graphql/static_validation/validation_context.rb +13 -3
- data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
- data/lib/graphql/static_validation/validator.rb +43 -9
- data/lib/graphql/static_validation.rb +1 -0
- data/lib/graphql/string_encoding_error.rb +13 -3
- data/lib/graphql/string_type.rb +1 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +123 -22
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +21 -0
- data/lib/graphql/subscriptions/event.rb +94 -26
- data/lib/graphql/subscriptions/instrumentation.rb +10 -6
- data/lib/graphql/subscriptions/serialize.rb +53 -6
- data/lib/graphql/subscriptions/subscription_root.rb +15 -5
- data/lib/graphql/subscriptions.rb +122 -54
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +8 -17
- data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
- data/lib/graphql/tracing/appsignal_tracing.rb +23 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +32 -2
- data/lib/graphql/tracing/new_relic_tracing.rb +9 -12
- data/lib/graphql/tracing/notifications_tracing.rb +59 -0
- data/lib/graphql/tracing/platform_tracing.rb +66 -7
- data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
- data/lib/graphql/tracing/prometheus_tracing.rb +8 -0
- data/lib/graphql/tracing/scout_tracing.rb +19 -0
- data/lib/graphql/tracing/skylight_tracing.rb +9 -0
- data/lib/graphql/tracing/statsd_tracing.rb +42 -0
- data/lib/graphql/tracing.rb +15 -35
- data/lib/graphql/types/big_int.rb +5 -1
- data/lib/graphql/types/int.rb +10 -3
- data/lib/graphql/types/iso_8601_date.rb +42 -0
- data/lib/graphql/types/iso_8601_date_time.rb +32 -8
- data/lib/graphql/types/relay/base_connection.rb +6 -88
- data/lib/graphql/types/relay/base_edge.rb +2 -37
- data/lib/graphql/types/relay/connection_behaviors.rb +174 -0
- data/lib/graphql/types/relay/default_relay.rb +31 -0
- data/lib/graphql/types/relay/edge_behaviors.rb +64 -0
- data/lib/graphql/types/relay/has_node_field.rb +41 -0
- data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
- data/lib/graphql/types/relay/node.rb +2 -4
- data/lib/graphql/types/relay/node_behaviors.rb +15 -0
- data/lib/graphql/types/relay/node_field.rb +4 -23
- data/lib/graphql/types/relay/nodes_field.rb +16 -18
- data/lib/graphql/types/relay/page_info.rb +2 -14
- data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
- data/lib/graphql/types/relay.rb +11 -3
- data/lib/graphql/types/string.rb +8 -2
- data/lib/graphql/types.rb +1 -0
- data/lib/graphql/unauthorized_error.rb +2 -2
- data/lib/graphql/union_type.rb +61 -46
- data/lib/graphql/unresolved_type_error.rb +2 -2
- data/lib/graphql/upgrader/member.rb +150 -112
- data/lib/graphql/upgrader/schema.rb +1 -0
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +89 -18
- data/readme.md +4 -7
- metadata +115 -703
- data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
- data/lib/graphql/literal_validation_error.rb +0 -6
- data/lib/graphql/types/relay/base_field.rb +0 -22
- data/lib/graphql/types/relay/base_interface.rb +0 -29
- data/lib/graphql/types/relay/base_object.rb +0 -26
- data/spec/dummy/Gemfile +0 -12
- data/spec/dummy/Gemfile.lock +0 -157
- data/spec/dummy/README.md +0 -24
- data/spec/dummy/Rakefile +0 -7
- data/spec/dummy/app/assets/config/manifest.js +0 -1
- data/spec/dummy/app/assets/javascripts/application.js +0 -66
- data/spec/dummy/app/channels/application_cable/channel.rb +0 -5
- data/spec/dummy/app/channels/application_cable/connection.rb +0 -5
- data/spec/dummy/app/channels/graphql_channel.rb +0 -116
- data/spec/dummy/app/controllers/application_controller.rb +0 -4
- data/spec/dummy/app/controllers/pages_controller.rb +0 -5
- data/spec/dummy/app/helpers/application_helper.rb +0 -3
- data/spec/dummy/app/jobs/application_job.rb +0 -3
- data/spec/dummy/app/views/layouts/application.html.erb +0 -12
- data/spec/dummy/app/views/pages/show.html +0 -16
- data/spec/dummy/bin/bundle +0 -4
- data/spec/dummy/bin/rails +0 -5
- data/spec/dummy/bin/rake +0 -5
- data/spec/dummy/bin/setup +0 -31
- data/spec/dummy/bin/update +0 -27
- data/spec/dummy/bin/yarn +0 -12
- data/spec/dummy/config/application.rb +0 -30
- data/spec/dummy/config/boot.rb +0 -4
- data/spec/dummy/config/cable.yml +0 -10
- data/spec/dummy/config/environment.rb +0 -6
- data/spec/dummy/config/environments/development.rb +0 -40
- data/spec/dummy/config/environments/production.rb +0 -76
- data/spec/dummy/config/environments/test.rb +0 -37
- data/spec/dummy/config/initializers/application_controller_renderer.rb +0 -9
- data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -8
- data/spec/dummy/config/initializers/cookies_serializer.rb +0 -6
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +0 -5
- data/spec/dummy/config/initializers/inflections.rb +0 -17
- data/spec/dummy/config/initializers/mime_types.rb +0 -5
- data/spec/dummy/config/initializers/wrap_parameters.rb +0 -10
- data/spec/dummy/config/locales/en.yml +0 -33
- data/spec/dummy/config/puma.rb +0 -57
- data/spec/dummy/config/routes.rb +0 -4
- data/spec/dummy/config/secrets.yml +0 -32
- data/spec/dummy/config.ru +0 -6
- data/spec/dummy/log/test.log +0 -199
- data/spec/dummy/package.json +0 -5
- data/spec/dummy/public/404.html +0 -67
- data/spec/dummy/public/422.html +0 -67
- data/spec/dummy/public/500.html +0 -66
- data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
- data/spec/dummy/public/apple-touch-icon.png +0 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/robots.txt +0 -1
- data/spec/dummy/test/application_system_test_case.rb +0 -6
- data/spec/dummy/test/system/action_cable_subscription_test.rb +0 -45
- data/spec/dummy/test/test_helper.rb +0 -4
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/4w/4wzXRZrAkwKdgYaSE0pid5eB-fer8vSfSku_NPg4rMA.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/7I/7IHVBiJT06QSpgLpLoJIxboQ0B-D_tMTxsvoezBTV3Q.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8w/8wY_SKagj8wHuwGNAAf6JnQ8joMbC6cEYpHrTAI8Urc.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/AK/AKzz1u6bGb4auXcrObA_g5LL-oV0ejNGa448AgAi_WQ.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ET/ETW4uxvaYpruL8y6_ZptUH82ZowMaHIqvg5WexBFdEM.cache +0 -3
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F1/F1TWpjjyA56k9Z90n5B3xRn7DUdGjX73QCkYC6k07JQ.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F8/F8MUNRzORGFgr329fNM0xLaoWCXdv3BIalT7dsvLfjs.cache +0 -2
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/KB/KB07ZaKNC5uXJ7TjLi-WqnY6g7dq8wWp_8N3HNjBNxg.cache +0 -2
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ms/MsKSimH_UCB-H1tLvDABDHuvGciuoW6kVqQWDrXU5FQ.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Mt/Mtci-Kim50aPOmeClD4AIicKn1d1WJ0n454IjSd94sk.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/QH/QHt3Tc1Y6M66Oo_pDuMyWrQNs4Pp3SMeZR5K1wJj2Ts.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/XU/XU4k1OXnfMils5SrirorPvDSyDSqiOWLZNtmAH1HH8k.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ZI/ZIof7mZxWWCnraIFOCuV6a8QRWzKJXJnx2Xd7C0ZyX0.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/cG/cGc_puuPS5pZKgUcy1Y_i1L6jl5UtsiIrMH59rTzR6c.cache +0 -3
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/df/dfro_B6bx3KP1Go-7jEOqqZ2j4hVRseXIc3es9PKQno.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/jO/jO1DfbqnG0mTULsjJJANc3fefrG2zt7DIMmcptMT628.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/pE/pE7gO6pQ-z187Swb4hT554wmqsq-cNzgPWLrCz-LQQQ.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/r9/r9iU1l58a6rxkZSW5RSC52_tD-_UQuHxoMVnkfJ7Mhs.cache +0 -1
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/xi/xitPPFfPIyDMpaznV0sBBcw8eSCV8PJcLLWin78sCgE.cache +0 -0
- data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
- data/spec/fixtures/upgrader/account.original.rb +0 -19
- data/spec/fixtures/upgrader/account.transformed.rb +0 -20
- data/spec/fixtures/upgrader/blame_range.original.rb +0 -43
- data/spec/fixtures/upgrader/blame_range.transformed.rb +0 -30
- data/spec/fixtures/upgrader/date_time.original.rb +0 -24
- data/spec/fixtures/upgrader/date_time.transformed.rb +0 -23
- data/spec/fixtures/upgrader/delete_project.original.rb +0 -28
- data/spec/fixtures/upgrader/delete_project.transformed.rb +0 -27
- data/spec/fixtures/upgrader/gist_order_field.original.rb +0 -14
- data/spec/fixtures/upgrader/gist_order_field.transformed.rb +0 -13
- data/spec/fixtures/upgrader/increment_count.original.rb +0 -59
- data/spec/fixtures/upgrader/increment_count.transformed.rb +0 -50
- data/spec/fixtures/upgrader/photo.original.rb +0 -10
- data/spec/fixtures/upgrader/photo.transformed.rb +0 -12
- data/spec/fixtures/upgrader/release_order.original.rb +0 -15
- data/spec/fixtures/upgrader/release_order.transformed.rb +0 -14
- data/spec/fixtures/upgrader/starrable.original.rb +0 -49
- data/spec/fixtures/upgrader/starrable.transformed.rb +0 -46
- data/spec/fixtures/upgrader/subscribable.original.rb +0 -55
- data/spec/fixtures/upgrader/subscribable.transformed.rb +0 -51
- data/spec/fixtures/upgrader/type_x.original.rb +0 -65
- data/spec/fixtures/upgrader/type_x.transformed.rb +0 -56
- data/spec/graphql/analysis/analyze_query_spec.rb +0 -272
- data/spec/graphql/analysis/ast/field_usage_spec.rb +0 -51
- data/spec/graphql/analysis/ast/max_query_complexity_spec.rb +0 -120
- data/spec/graphql/analysis/ast/max_query_depth_spec.rb +0 -114
- data/spec/graphql/analysis/ast/query_complexity_spec.rb +0 -299
- data/spec/graphql/analysis/ast/query_depth_spec.rb +0 -108
- data/spec/graphql/analysis/ast_spec.rb +0 -269
- data/spec/graphql/analysis/field_usage_spec.rb +0 -62
- data/spec/graphql/analysis/max_query_complexity_spec.rb +0 -102
- data/spec/graphql/analysis/max_query_depth_spec.rb +0 -101
- data/spec/graphql/analysis/query_complexity_spec.rb +0 -301
- data/spec/graphql/analysis/query_depth_spec.rb +0 -81
- data/spec/graphql/argument_spec.rb +0 -159
- data/spec/graphql/authorization_spec.rb +0 -974
- data/spec/graphql/backtrace_spec.rb +0 -206
- data/spec/graphql/base_type_spec.rb +0 -171
- data/spec/graphql/boolean_type_spec.rb +0 -21
- data/spec/graphql/compatibility/execution_specification_spec.rb +0 -4
- data/spec/graphql/compatibility/lazy_execution_specification_spec.rb +0 -4
- data/spec/graphql/compatibility/query_parser_specification_spec.rb +0 -6
- data/spec/graphql/compatibility/schema_parser_specification_spec.rb +0 -6
- data/spec/graphql/define/assign_argument_spec.rb +0 -61
- data/spec/graphql/define/instance_definable_spec.rb +0 -203
- data/spec/graphql/directive/skip_directive_spec.rb +0 -9
- data/spec/graphql/directive_spec.rb +0 -295
- data/spec/graphql/enum_type_spec.rb +0 -158
- data/spec/graphql/execution/execute_spec.rb +0 -303
- data/spec/graphql/execution/instrumentation_spec.rb +0 -184
- data/spec/graphql/execution/interpreter_spec.rb +0 -485
- data/spec/graphql/execution/lazy/lazy_method_map_spec.rb +0 -57
- data/spec/graphql/execution/lazy_spec.rb +0 -247
- data/spec/graphql/execution/lookahead_spec.rb +0 -390
- data/spec/graphql/execution/multiplex_spec.rb +0 -211
- data/spec/graphql/execution/typecast_spec.rb +0 -47
- data/spec/graphql/execution_error_spec.rb +0 -325
- data/spec/graphql/field_spec.rb +0 -246
- data/spec/graphql/float_type_spec.rb +0 -16
- data/spec/graphql/function_spec.rb +0 -152
- data/spec/graphql/id_type_spec.rb +0 -33
- data/spec/graphql/input_object_type_spec.rb +0 -25
- data/spec/graphql/int_type_spec.rb +0 -35
- data/spec/graphql/interface_type_spec.rb +0 -196
- data/spec/graphql/internal_representation/print_spec.rb +0 -41
- data/spec/graphql/internal_representation/rewrite_spec.rb +0 -376
- data/spec/graphql/introspection/directive_type_spec.rb +0 -61
- data/spec/graphql/introspection/input_value_type_spec.rb +0 -144
- data/spec/graphql/introspection/introspection_query_spec.rb +0 -59
- data/spec/graphql/introspection/schema_type_spec.rb +0 -56
- data/spec/graphql/introspection/type_type_spec.rb +0 -155
- data/spec/graphql/language/block_string_spec.rb +0 -70
- data/spec/graphql/language/definition_slice_spec.rb +0 -226
- data/spec/graphql/language/document_from_schema_definition_spec.rb +0 -770
- data/spec/graphql/language/equality_spec.rb +0 -84
- data/spec/graphql/language/generation_spec.rb +0 -38
- data/spec/graphql/language/lexer_spec.rb +0 -135
- data/spec/graphql/language/nodes_spec.rb +0 -67
- data/spec/graphql/language/parser_spec.rb +0 -183
- data/spec/graphql/language/printer_spec.rb +0 -215
- data/spec/graphql/language/visitor_spec.rb +0 -419
- data/spec/graphql/list_type_spec.rb +0 -57
- data/spec/graphql/non_null_type_spec.rb +0 -48
- data/spec/graphql/object_type_spec.rb +0 -197
- data/spec/graphql/query/arguments_spec.rb +0 -346
- data/spec/graphql/query/context_spec.rb +0 -292
- data/spec/graphql/query/executor_spec.rb +0 -341
- data/spec/graphql/query/literal_input_spec.rb +0 -91
- data/spec/graphql/query/result_spec.rb +0 -29
- data/spec/graphql/query/serial_execution/value_resolution_spec.rb +0 -109
- data/spec/graphql/query_spec.rb +0 -800
- data/spec/graphql/rake_task_spec.rb +0 -59
- data/spec/graphql/scalar_type_spec.rb +0 -66
- data/spec/graphql/schema/argument_spec.rb +0 -152
- data/spec/graphql/schema/build_from_definition_spec.rb +0 -1187
- data/spec/graphql/schema/catchall_middleware_spec.rb +0 -35
- data/spec/graphql/schema/directive/feature_spec.rb +0 -81
- data/spec/graphql/schema/directive/transform_spec.rb +0 -39
- data/spec/graphql/schema/enum_spec.rb +0 -83
- data/spec/graphql/schema/enum_value_spec.rb +0 -24
- data/spec/graphql/schema/field_extension_spec.rb +0 -137
- data/spec/graphql/schema/field_spec.rb +0 -301
- data/spec/graphql/schema/finder_spec.rb +0 -135
- data/spec/graphql/schema/input_object_spec.rb +0 -347
- data/spec/graphql/schema/instrumentation_spec.rb +0 -43
- data/spec/graphql/schema/interface_spec.rb +0 -215
- data/spec/graphql/schema/introspection_system_spec.rb +0 -56
- data/spec/graphql/schema/list_spec.rb +0 -46
- data/spec/graphql/schema/loader_spec.rb +0 -286
- data/spec/graphql/schema/member/accepts_definition_spec.rb +0 -115
- data/spec/graphql/schema/member/build_type_spec.rb +0 -63
- data/spec/graphql/schema/member/scoped_spec.rb +0 -217
- data/spec/graphql/schema/member/type_system_helpers_spec.rb +0 -63
- data/spec/graphql/schema/middleware_chain_spec.rb +0 -57
- data/spec/graphql/schema/mutation_spec.rb +0 -150
- data/spec/graphql/schema/non_null_spec.rb +0 -46
- data/spec/graphql/schema/object_spec.rb +0 -315
- data/spec/graphql/schema/printer_spec.rb +0 -869
- data/spec/graphql/schema/relay_classic_mutation_spec.rb +0 -252
- data/spec/graphql/schema/rescue_middleware_spec.rb +0 -88
- data/spec/graphql/schema/resolver_spec.rb +0 -714
- data/spec/graphql/schema/scalar_spec.rb +0 -101
- data/spec/graphql/schema/subscription_spec.rb +0 -440
- data/spec/graphql/schema/timeout_middleware_spec.rb +0 -188
- data/spec/graphql/schema/traversal_spec.rb +0 -222
- data/spec/graphql/schema/type_expression_spec.rb +0 -39
- data/spec/graphql/schema/union_spec.rb +0 -72
- data/spec/graphql/schema/unique_within_type_spec.rb +0 -44
- data/spec/graphql/schema/validation_spec.rb +0 -355
- data/spec/graphql/schema/warden_spec.rb +0 -926
- data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +0 -413
- data/spec/graphql/static_validation/rules/argument_names_are_unique_spec.rb +0 -44
- data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +0 -112
- data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +0 -35
- data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +0 -42
- data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +0 -167
- data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +0 -66
- data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +0 -740
- data/spec/graphql/static_validation/rules/fragment_names_are_unique_spec.rb +0 -28
- data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +0 -52
- data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +0 -42
- data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +0 -123
- data/spec/graphql/static_validation/rules/fragments_are_named_spec.rb +0 -24
- data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +0 -56
- data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +0 -61
- data/spec/graphql/static_validation/rules/mutation_root_exists_spec.rb +0 -39
- data/spec/graphql/static_validation/rules/no_definitions_are_present_spec.rb +0 -62
- data/spec/graphql/static_validation/rules/operation_names_are_valid_spec.rb +0 -82
- data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +0 -73
- data/spec/graphql/static_validation/rules/required_input_object_attributes_are_present_spec.rb +0 -86
- data/spec/graphql/static_validation/rules/subscription_root_exists_spec.rb +0 -34
- data/spec/graphql/static_validation/rules/unique_directives_per_location_spec.rb +0 -188
- data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +0 -196
- data/spec/graphql/static_validation/rules/variable_names_are_unique_spec.rb +0 -23
- data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +0 -236
- data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +0 -78
- data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +0 -81
- data/spec/graphql/static_validation/type_stack_spec.rb +0 -29
- data/spec/graphql/static_validation/validator_spec.rb +0 -204
- data/spec/graphql/string_type_spec.rb +0 -80
- data/spec/graphql/subscriptions/serialize_spec.rb +0 -49
- data/spec/graphql/subscriptions_spec.rb +0 -540
- data/spec/graphql/tracing/new_relic_tracing_spec.rb +0 -84
- data/spec/graphql/tracing/platform_tracing_spec.rb +0 -141
- data/spec/graphql/tracing/prometheus_tracing_spec.rb +0 -42
- data/spec/graphql/tracing/scout_tracing_spec.rb +0 -17
- data/spec/graphql/tracing/skylight_tracing_spec.rb +0 -63
- data/spec/graphql/tracing_spec.rb +0 -52
- data/spec/graphql/types/big_int_spec.rb +0 -24
- data/spec/graphql/types/iso_8601_date_time_spec.rb +0 -137
- data/spec/graphql/types/relay/base_edge_spec.rb +0 -33
- data/spec/graphql/union_type_spec.rb +0 -211
- data/spec/graphql/upgrader/member_spec.rb +0 -583
- data/spec/graphql/upgrader/schema_spec.rb +0 -82
- data/spec/integration/mongoid/graphql/relay/mongo_relation_connection_spec.rb +0 -528
- data/spec/integration/mongoid/spec_helper.rb +0 -2
- data/spec/integration/mongoid/star_trek/data.rb +0 -126
- data/spec/integration/mongoid/star_trek/schema.rb +0 -425
- data/spec/integration/rails/data.rb +0 -110
- data/spec/integration/rails/generators/base_generator_test.rb +0 -7
- data/spec/integration/rails/generators/graphql/enum_generator_spec.rb +0 -30
- data/spec/integration/rails/generators/graphql/install_generator_spec.rb +0 -218
- data/spec/integration/rails/generators/graphql/interface_generator_spec.rb +0 -34
- data/spec/integration/rails/generators/graphql/loader_generator_spec.rb +0 -59
- data/spec/integration/rails/generators/graphql/mutation_generator_spec.rb +0 -71
- data/spec/integration/rails/generators/graphql/object_generator_spec.rb +0 -54
- data/spec/integration/rails/generators/graphql/scalar_generator_spec.rb +0 -28
- data/spec/integration/rails/generators/graphql/union_generator_spec.rb +0 -67
- data/spec/integration/rails/graphql/input_object_type_spec.rb +0 -364
- data/spec/integration/rails/graphql/query/variables_spec.rb +0 -375
- data/spec/integration/rails/graphql/relay/array_connection_spec.rb +0 -290
- data/spec/integration/rails/graphql/relay/base_connection_spec.rb +0 -101
- data/spec/integration/rails/graphql/relay/connection_instrumentation_spec.rb +0 -80
- data/spec/integration/rails/graphql/relay/connection_resolve_spec.rb +0 -79
- data/spec/integration/rails/graphql/relay/connection_type_spec.rb +0 -106
- data/spec/integration/rails/graphql/relay/edge_spec.rb +0 -10
- data/spec/integration/rails/graphql/relay/mutation_spec.rb +0 -387
- data/spec/integration/rails/graphql/relay/node_spec.rb +0 -263
- data/spec/integration/rails/graphql/relay/page_info_spec.rb +0 -111
- data/spec/integration/rails/graphql/relay/range_add_spec.rb +0 -117
- data/spec/integration/rails/graphql/relay/relation_connection_spec.rb +0 -837
- data/spec/integration/rails/graphql/schema_spec.rb +0 -489
- data/spec/integration/rails/graphql/tracing/active_support_notifications_tracing_spec.rb +0 -62
- data/spec/integration/rails/spec_helper.rb +0 -25
- data/spec/integration/tmp/app/graphql/types/bird_type.rb +0 -7
- data/spec/spec_helper.rb +0 -116
- data/spec/support/dummy/data.rb +0 -45
- data/spec/support/dummy/schema.rb +0 -511
- data/spec/support/error_bubbling_helpers.rb +0 -23
- data/spec/support/global_id.rb +0 -23
- data/spec/support/jazz.rb +0 -772
- data/spec/support/lazy_helpers.rb +0 -192
- data/spec/support/magic_cards/schema.graphql +0 -33
- data/spec/support/minimum_input_object.rb +0 -21
- data/spec/support/new_relic.rb +0 -27
- data/spec/support/parser/filename_example.graphql +0 -5
- data/spec/support/parser/filename_example_error_1.graphql +0 -4
- data/spec/support/parser/filename_example_error_2.graphql +0 -5
- data/spec/support/skylight.rb +0 -39
- data/spec/support/star_wars/schema.rb +0 -465
- data/spec/support/static_validation_helpers.rb +0 -32
@@ -8,67 +8,279 @@ module GraphQL
|
|
8
8
|
#
|
9
9
|
# @api private
|
10
10
|
class Runtime
|
11
|
+
|
12
|
+
module GraphQLResult
|
13
|
+
def initialize(result_name, parent_result)
|
14
|
+
@graphql_parent = parent_result
|
15
|
+
if parent_result && parent_result.graphql_dead
|
16
|
+
@graphql_dead = true
|
17
|
+
end
|
18
|
+
@graphql_result_name = result_name
|
19
|
+
# Jump through some hoops to avoid creating this duplicate storage if at all possible.
|
20
|
+
@graphql_metadata = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_accessor :graphql_dead
|
24
|
+
attr_reader :graphql_parent, :graphql_result_name
|
25
|
+
|
26
|
+
# Although these are used by only one of the Result classes,
|
27
|
+
# it's handy to have the methods implemented on both (even though they just return `nil`)
|
28
|
+
# because it makes it easy to check if anything is assigned.
|
29
|
+
# @return [nil, Array<String>]
|
30
|
+
attr_accessor :graphql_non_null_field_names
|
31
|
+
# @return [nil, true]
|
32
|
+
attr_accessor :graphql_non_null_list_items
|
33
|
+
|
34
|
+
# @return [Hash] Plain-Ruby result data (`@graphql_metadata` contains Result wrapper objects)
|
35
|
+
attr_accessor :graphql_result_data
|
36
|
+
end
|
37
|
+
|
38
|
+
class GraphQLResultHash
|
39
|
+
def initialize(_result_name, _parent_result)
|
40
|
+
super
|
41
|
+
@graphql_result_data = {}
|
42
|
+
end
|
43
|
+
|
44
|
+
include GraphQLResult
|
45
|
+
|
46
|
+
attr_accessor :graphql_merged_into
|
47
|
+
|
48
|
+
def []=(key, value)
|
49
|
+
# This is a hack.
|
50
|
+
# Basically, this object is merged into the root-level result at some point.
|
51
|
+
# But the problem is, some lazies are created whose closures retain reference to _this_
|
52
|
+
# object. When those lazies are resolved, they cause an update to this object.
|
53
|
+
#
|
54
|
+
# In order to return a proper top-level result, we have to update that top-level result object.
|
55
|
+
# In order to return a proper partial result (eg, for a directive), we have to update this object, too.
|
56
|
+
# Yowza.
|
57
|
+
if (t = @graphql_merged_into)
|
58
|
+
t[key] = value
|
59
|
+
end
|
60
|
+
|
61
|
+
if value.respond_to?(:graphql_result_data)
|
62
|
+
@graphql_result_data[key] = value.graphql_result_data
|
63
|
+
# If we encounter some part of this response that requires metadata tracking,
|
64
|
+
# then create the metadata hash if necessary. It will be kept up-to-date after this.
|
65
|
+
(@graphql_metadata ||= @graphql_result_data.dup)[key] = value
|
66
|
+
else
|
67
|
+
@graphql_result_data[key] = value
|
68
|
+
# keep this up-to-date if it's been initialized
|
69
|
+
@graphql_metadata && @graphql_metadata[key] = value
|
70
|
+
end
|
71
|
+
|
72
|
+
value
|
73
|
+
end
|
74
|
+
|
75
|
+
def delete(key)
|
76
|
+
@graphql_metadata && @graphql_metadata.delete(key)
|
77
|
+
@graphql_result_data.delete(key)
|
78
|
+
end
|
79
|
+
|
80
|
+
def each
|
81
|
+
(@graphql_metadata || @graphql_result_data).each { |k, v| yield(k, v) }
|
82
|
+
end
|
83
|
+
|
84
|
+
def values
|
85
|
+
(@graphql_metadata || @graphql_result_data).values
|
86
|
+
end
|
87
|
+
|
88
|
+
def key?(k)
|
89
|
+
@graphql_result_data.key?(k)
|
90
|
+
end
|
91
|
+
|
92
|
+
def [](k)
|
93
|
+
(@graphql_metadata || @graphql_result_data)[k]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class GraphQLResultArray
|
98
|
+
include GraphQLResult
|
99
|
+
|
100
|
+
def initialize(_result_name, _parent_result)
|
101
|
+
super
|
102
|
+
@graphql_result_data = []
|
103
|
+
end
|
104
|
+
|
105
|
+
def graphql_skip_at(index)
|
106
|
+
# Mark this index as dead. It's tricky because some indices may already be storing
|
107
|
+
# `Lazy`s. So the runtime is still holding indexes _before_ skipping,
|
108
|
+
# this object has to coordinate incoming writes to account for any already-skipped indices.
|
109
|
+
@skip_indices ||= []
|
110
|
+
@skip_indices << index
|
111
|
+
offset_by = @skip_indices.count { |skipped_idx| skipped_idx < index}
|
112
|
+
delete_at_index = index - offset_by
|
113
|
+
@graphql_metadata && @graphql_metadata.delete_at(delete_at_index)
|
114
|
+
@graphql_result_data.delete_at(delete_at_index)
|
115
|
+
end
|
116
|
+
|
117
|
+
def []=(idx, value)
|
118
|
+
if @skip_indices
|
119
|
+
offset_by = @skip_indices.count { |skipped_idx| skipped_idx < idx }
|
120
|
+
idx -= offset_by
|
121
|
+
end
|
122
|
+
if value.respond_to?(:graphql_result_data)
|
123
|
+
@graphql_result_data[idx] = value.graphql_result_data
|
124
|
+
(@graphql_metadata ||= @graphql_result_data.dup)[idx] = value
|
125
|
+
else
|
126
|
+
@graphql_result_data[idx] = value
|
127
|
+
@graphql_metadata && @graphql_metadata[idx] = value
|
128
|
+
end
|
129
|
+
|
130
|
+
value
|
131
|
+
end
|
132
|
+
|
133
|
+
def values
|
134
|
+
(@graphql_metadata || @graphql_result_data)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
class GraphQLSelectionSet < Hash
|
139
|
+
attr_accessor :graphql_directives
|
140
|
+
end
|
141
|
+
|
11
142
|
# @return [GraphQL::Query]
|
12
143
|
attr_reader :query
|
13
144
|
|
14
|
-
# @return [Class]
|
145
|
+
# @return [Class<GraphQL::Schema>]
|
15
146
|
attr_reader :schema
|
16
147
|
|
17
148
|
# @return [GraphQL::Query::Context]
|
18
149
|
attr_reader :context
|
19
150
|
|
20
|
-
def initialize(query
|
151
|
+
def initialize(query:)
|
21
152
|
@query = query
|
153
|
+
@dataloader = query.multiplex.dataloader
|
22
154
|
@schema = query.schema
|
23
155
|
@context = query.context
|
156
|
+
@multiplex_context = query.multiplex.context
|
24
157
|
@interpreter_context = @context.namespace(:interpreter)
|
25
|
-
@response =
|
26
|
-
|
27
|
-
@
|
158
|
+
@response = GraphQLResultHash.new(nil, nil)
|
159
|
+
# Identify runtime directives by checking which of this schema's directives have overridden `def self.resolve`
|
160
|
+
@runtime_directive_names = []
|
161
|
+
noop_resolve_owner = GraphQL::Schema::Directive.singleton_class
|
162
|
+
@schema_directives = schema.directives
|
163
|
+
@schema_directives.each do |name, dir_defn|
|
164
|
+
if dir_defn.method(:resolve).owner != noop_resolve_owner
|
165
|
+
@runtime_directive_names << name
|
166
|
+
end
|
167
|
+
end
|
28
168
|
# A cache of { Class => { String => Schema::Field } }
|
29
169
|
# Which assumes that MyObject.get_field("myField") will return the same field
|
30
170
|
# during the lifetime of a query
|
31
171
|
@fields_cache = Hash.new { |h, k| h[k] = {} }
|
172
|
+
# { Class => Boolean }
|
173
|
+
@lazy_cache = {}
|
32
174
|
end
|
33
175
|
|
34
|
-
def
|
35
|
-
@response.
|
176
|
+
def final_result
|
177
|
+
@response && @response.graphql_result_data
|
36
178
|
end
|
37
179
|
|
38
180
|
def inspect
|
39
181
|
"#<#{self.class.name} response=#{@response.inspect}>"
|
40
182
|
end
|
41
183
|
|
184
|
+
def tap_or_each(obj_or_array)
|
185
|
+
if obj_or_array.is_a?(Array)
|
186
|
+
obj_or_array.each do |item|
|
187
|
+
yield(item, true)
|
188
|
+
end
|
189
|
+
else
|
190
|
+
yield(obj_or_array, false)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
42
194
|
# This _begins_ the execution. Some deferred work
|
43
195
|
# might be stored up in lazies.
|
44
196
|
# @return [void]
|
45
197
|
def run_eager
|
46
198
|
root_operation = query.selected_operation
|
47
199
|
root_op_type = root_operation.operation_type || "query"
|
48
|
-
|
49
|
-
|
50
|
-
|
200
|
+
root_type = schema.root_type_for_operation(root_op_type)
|
201
|
+
path = []
|
202
|
+
set_all_interpreter_context(query.root_value, nil, nil, path)
|
203
|
+
object_proxy = authorized_new(root_type, query.root_value, context)
|
51
204
|
object_proxy = schema.sync_lazy(object_proxy)
|
205
|
+
|
52
206
|
if object_proxy.nil?
|
53
207
|
# Root .authorized? returned false.
|
54
|
-
|
55
|
-
nil
|
208
|
+
@response = nil
|
56
209
|
else
|
57
|
-
|
58
|
-
|
59
|
-
|
210
|
+
call_method_on_directives(:resolve, object_proxy, root_operation.directives) do # execute query level directives
|
211
|
+
gathered_selections = gather_selections(object_proxy, root_type, root_operation.selections)
|
212
|
+
# This is kind of a hack -- `gathered_selections` is an Array if any of the selections
|
213
|
+
# require isolation during execution (because of runtime directives). In that case,
|
214
|
+
# make a new, isolated result hash for writing the result into. (That isolated response
|
215
|
+
# is eventually merged back into the main response)
|
216
|
+
#
|
217
|
+
# Otherwise, `gathered_selections` is a hash of selections which can be
|
218
|
+
# directly evaluated and the results can be written right into the main response hash.
|
219
|
+
tap_or_each(gathered_selections) do |selections, is_selection_array|
|
220
|
+
if is_selection_array
|
221
|
+
selection_response = GraphQLResultHash.new(nil, nil)
|
222
|
+
final_response = @response
|
223
|
+
else
|
224
|
+
selection_response = @response
|
225
|
+
final_response = nil
|
226
|
+
end
|
227
|
+
|
228
|
+
@dataloader.append_job {
|
229
|
+
set_all_interpreter_context(query.root_value, nil, nil, path)
|
230
|
+
call_method_on_directives(:resolve, object_proxy, selections.graphql_directives) do
|
231
|
+
evaluate_selections(
|
232
|
+
path,
|
233
|
+
context.scoped_context,
|
234
|
+
object_proxy,
|
235
|
+
root_type,
|
236
|
+
root_op_type == "mutation",
|
237
|
+
selections,
|
238
|
+
selection_response,
|
239
|
+
final_response,
|
240
|
+
nil,
|
241
|
+
)
|
242
|
+
end
|
243
|
+
}
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
delete_interpreter_context(:current_path)
|
248
|
+
delete_interpreter_context(:current_field)
|
249
|
+
delete_interpreter_context(:current_object)
|
250
|
+
delete_interpreter_context(:current_arguments)
|
251
|
+
nil
|
252
|
+
end
|
253
|
+
|
254
|
+
# @return [void]
|
255
|
+
def deep_merge_selection_result(from_result, into_result)
|
256
|
+
from_result.each do |key, value|
|
257
|
+
if !into_result.key?(key)
|
258
|
+
into_result[key] = value
|
259
|
+
else
|
260
|
+
case value
|
261
|
+
when GraphQLResultHash
|
262
|
+
deep_merge_selection_result(value, into_result[key])
|
263
|
+
else
|
264
|
+
# We have to assume that, since this passed the `fields_will_merge` selection,
|
265
|
+
# that the old and new values are the same.
|
266
|
+
# There's no special handling of arrays because currently, there's no way to split the execution
|
267
|
+
# of a list over several concurrent flows.
|
268
|
+
into_result[key] = value
|
269
|
+
end
|
270
|
+
end
|
60
271
|
end
|
272
|
+
from_result.graphql_merged_into = into_result
|
273
|
+
nil
|
61
274
|
end
|
62
275
|
|
63
|
-
def gather_selections(owner_object, owner_type, selections, selections_by_name)
|
276
|
+
def gather_selections(owner_object, owner_type, selections, selections_to_run = nil, selections_by_name = GraphQLSelectionSet.new)
|
64
277
|
selections.each do |node|
|
65
278
|
# Skip gathering this if the directive says so
|
66
279
|
if !directives_include?(node, owner_object, owner_type)
|
67
280
|
next
|
68
281
|
end
|
69
282
|
|
70
|
-
|
71
|
-
when GraphQL::Language::Nodes::Field
|
283
|
+
if node.is_a?(GraphQL::Language::Nodes::Field)
|
72
284
|
response_key = node.alias || node.name
|
73
285
|
selections = selections_by_name[response_key]
|
74
286
|
# if there was already a selection of this field,
|
@@ -84,134 +296,228 @@ module GraphQL
|
|
84
296
|
# No selection was found for this field yet
|
85
297
|
selections_by_name[response_key] = node
|
86
298
|
end
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
299
|
+
else
|
300
|
+
# This is an InlineFragment or a FragmentSpread
|
301
|
+
if @runtime_directive_names.any? && node.directives.any? { |d| @runtime_directive_names.include?(d.name) }
|
302
|
+
next_selections = GraphQLSelectionSet.new
|
303
|
+
next_selections.graphql_directives = node.directives
|
304
|
+
if selections_to_run
|
305
|
+
selections_to_run << next_selections
|
306
|
+
else
|
307
|
+
selections_to_run = []
|
308
|
+
selections_to_run << selections_by_name
|
309
|
+
selections_to_run << next_selections
|
97
310
|
end
|
98
311
|
else
|
99
|
-
|
100
|
-
gather_selections(owner_object, owner_type, node.selections, selections_by_name)
|
312
|
+
next_selections = selections_by_name
|
101
313
|
end
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
314
|
+
|
315
|
+
case node
|
316
|
+
when GraphQL::Language::Nodes::InlineFragment
|
317
|
+
if node.type
|
318
|
+
type_defn = schema.get_type(node.type.name, context)
|
319
|
+
|
320
|
+
# Faster than .map{}.include?()
|
321
|
+
query.warden.possible_types(type_defn).each do |t|
|
322
|
+
if t == owner_type
|
323
|
+
gather_selections(owner_object, owner_type, node.selections, selections_to_run, next_selections)
|
324
|
+
break
|
325
|
+
end
|
326
|
+
end
|
327
|
+
else
|
328
|
+
# it's an untyped fragment, definitely continue
|
329
|
+
gather_selections(owner_object, owner_type, node.selections, selections_to_run, next_selections)
|
110
330
|
end
|
331
|
+
when GraphQL::Language::Nodes::FragmentSpread
|
332
|
+
fragment_def = query.fragments[node.name]
|
333
|
+
type_defn = query.get_type(fragment_def.type.name)
|
334
|
+
possible_types = query.warden.possible_types(type_defn)
|
335
|
+
possible_types.each do |t|
|
336
|
+
if t == owner_type
|
337
|
+
gather_selections(owner_object, owner_type, fragment_def.selections, selections_to_run, next_selections)
|
338
|
+
break
|
339
|
+
end
|
340
|
+
end
|
341
|
+
else
|
342
|
+
raise "Invariant: unexpected selection class: #{node.class}"
|
111
343
|
end
|
112
|
-
else
|
113
|
-
raise "Invariant: unexpected selection class: #{node.class}"
|
114
344
|
end
|
115
345
|
end
|
346
|
+
selections_to_run || selections_by_name
|
116
347
|
end
|
117
348
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
is_introspection = false
|
135
|
-
if field_defn.nil?
|
136
|
-
field_defn = if owner_type == schema.query.metadata[:type_class] && (entry_point_field = schema.introspection_system.entry_point(name: field_name))
|
137
|
-
is_introspection = true
|
138
|
-
entry_point_field.metadata[:type_class]
|
139
|
-
elsif (dynamic_field = schema.introspection_system.dynamic_field(name: field_name))
|
140
|
-
is_introspection = true
|
141
|
-
dynamic_field.metadata[:type_class]
|
142
|
-
else
|
143
|
-
raise "Invariant: no field for #{owner_type}.#{field_name}"
|
349
|
+
NO_ARGS = {}.freeze
|
350
|
+
|
351
|
+
# @return [void]
|
352
|
+
def evaluate_selections(path, scoped_context, owner_object, owner_type, is_eager_selection, gathered_selections, selections_result, target_result, parent_object) # rubocop:disable Metrics/ParameterLists
|
353
|
+
set_all_interpreter_context(owner_object, nil, nil, path)
|
354
|
+
|
355
|
+
finished_jobs = 0
|
356
|
+
enqueued_jobs = gathered_selections.size
|
357
|
+
gathered_selections.each do |result_name, field_ast_nodes_or_ast_node|
|
358
|
+
@dataloader.append_job {
|
359
|
+
evaluate_selection(
|
360
|
+
path, result_name, field_ast_nodes_or_ast_node, scoped_context, owner_object, owner_type, is_eager_selection, selections_result, parent_object
|
361
|
+
)
|
362
|
+
finished_jobs += 1
|
363
|
+
if target_result && finished_jobs == enqueued_jobs
|
364
|
+
deep_merge_selection_result(selections_result, target_result)
|
144
365
|
end
|
366
|
+
}
|
367
|
+
end
|
368
|
+
|
369
|
+
selections_result
|
370
|
+
end
|
371
|
+
|
372
|
+
attr_reader :progress_path
|
373
|
+
|
374
|
+
# @return [void]
|
375
|
+
def evaluate_selection(path, result_name, field_ast_nodes_or_ast_node, scoped_context, owner_object, owner_type, is_eager_field, selections_result, parent_object) # rubocop:disable Metrics/ParameterLists
|
376
|
+
return if dead_result?(selections_result)
|
377
|
+
# As a performance optimization, the hash key will be a `Node` if
|
378
|
+
# there's only one selection of the field. But if there are multiple
|
379
|
+
# selections of the field, it will be an Array of nodes
|
380
|
+
if field_ast_nodes_or_ast_node.is_a?(Array)
|
381
|
+
field_ast_nodes = field_ast_nodes_or_ast_node
|
382
|
+
ast_node = field_ast_nodes.first
|
383
|
+
else
|
384
|
+
field_ast_nodes = nil
|
385
|
+
ast_node = field_ast_nodes_or_ast_node
|
386
|
+
end
|
387
|
+
field_name = ast_node.name
|
388
|
+
# This can't use `query.get_field` because it gets confused on introspection below if `field_defn` isn't `nil`,
|
389
|
+
# because of how `is_introspection` is used to call `.authorized_new` later on.
|
390
|
+
field_defn = @fields_cache[owner_type][field_name] ||= owner_type.get_field(field_name, @context)
|
391
|
+
is_introspection = false
|
392
|
+
if field_defn.nil?
|
393
|
+
field_defn = if owner_type == schema.query && (entry_point_field = schema.introspection_system.entry_point(name: field_name))
|
394
|
+
is_introspection = true
|
395
|
+
entry_point_field
|
396
|
+
elsif (dynamic_field = schema.introspection_system.dynamic_field(name: field_name))
|
397
|
+
is_introspection = true
|
398
|
+
dynamic_field
|
399
|
+
else
|
400
|
+
raise "Invariant: no field for #{owner_type}.#{field_name}"
|
145
401
|
end
|
402
|
+
end
|
403
|
+
|
404
|
+
return_type = field_defn.type
|
146
405
|
|
147
|
-
|
406
|
+
next_path = path.dup
|
407
|
+
next_path << result_name
|
408
|
+
next_path.freeze
|
148
409
|
|
149
|
-
|
150
|
-
|
151
|
-
|
410
|
+
# This seems janky, but we need to know
|
411
|
+
# the field's return type at this path in order
|
412
|
+
# to propagate `null`
|
413
|
+
if return_type.non_null?
|
414
|
+
(selections_result.graphql_non_null_field_names ||= []).push(result_name)
|
415
|
+
end
|
416
|
+
# Set this before calling `run_with_directives`, so that the directive can have the latest path
|
417
|
+
set_all_interpreter_context(nil, field_defn, nil, next_path)
|
152
418
|
|
153
|
-
|
154
|
-
|
155
|
-
# to propagate `null`
|
156
|
-
set_type_at_path(next_path, return_type)
|
157
|
-
# Set this before calling `run_with_directives`, so that the directive can have the latest path
|
158
|
-
@interpreter_context[:current_path] = next_path
|
159
|
-
@interpreter_context[:current_field] = field_defn
|
419
|
+
context.scoped_context = scoped_context
|
420
|
+
object = owner_object
|
160
421
|
|
161
|
-
|
422
|
+
if is_introspection
|
423
|
+
object = authorized_new(field_defn.owner, object, context)
|
424
|
+
end
|
162
425
|
|
163
|
-
|
164
|
-
|
426
|
+
total_args_count = field_defn.arguments(context).size
|
427
|
+
if total_args_count == 0
|
428
|
+
resolved_arguments = GraphQL::Execution::Interpreter::Arguments::EMPTY
|
429
|
+
evaluate_selection_with_args(resolved_arguments, field_defn, next_path, ast_node, field_ast_nodes, scoped_context, owner_type, object, is_eager_field, result_name, selections_result, parent_object, return_type)
|
430
|
+
else
|
431
|
+
# TODO remove all arguments(...) usages?
|
432
|
+
@query.arguments_cache.dataload_for(ast_node, field_defn, object) do |resolved_arguments|
|
433
|
+
evaluate_selection_with_args(resolved_arguments, field_defn, next_path, ast_node, field_ast_nodes, scoped_context, owner_type, object, is_eager_field, result_name, selections_result, parent_object, return_type)
|
165
434
|
end
|
435
|
+
end
|
436
|
+
end
|
166
437
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
438
|
+
def evaluate_selection_with_args(arguments, field_defn, next_path, ast_node, field_ast_nodes, scoped_context, owner_type, object, is_eager_field, result_name, selection_result, parent_object, return_type) # rubocop:disable Metrics/ParameterLists
|
439
|
+
context.scoped_context = scoped_context
|
440
|
+
after_lazy(arguments, owner: owner_type, field: field_defn, path: next_path, ast_node: ast_node, scoped_context: context.scoped_context, owner_object: object, arguments: arguments, result_name: result_name, result: selection_result) do |resolved_arguments|
|
441
|
+
if resolved_arguments.is_a?(GraphQL::ExecutionError) || resolved_arguments.is_a?(GraphQL::UnauthorizedError)
|
442
|
+
continue_value(next_path, resolved_arguments, owner_type, field_defn, return_type.non_null?, ast_node, result_name, selection_result)
|
171
443
|
next
|
172
444
|
end
|
173
445
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
446
|
+
kwarg_arguments = if resolved_arguments.empty? && field_defn.extras.empty?
|
447
|
+
# We can avoid allocating the `{ Symbol => Object }` hash in this case
|
448
|
+
NO_ARGS
|
449
|
+
else
|
450
|
+
# Bundle up the extras, then make a new arguments instance
|
451
|
+
# that includes the extras, too.
|
452
|
+
extra_args = {}
|
453
|
+
field_defn.extras.each do |extra|
|
454
|
+
case extra
|
455
|
+
when :ast_node
|
456
|
+
extra_args[:ast_node] = ast_node
|
457
|
+
when :execution_errors
|
458
|
+
extra_args[:execution_errors] = ExecutionErrors.new(context, ast_node, next_path)
|
459
|
+
when :path
|
460
|
+
extra_args[:path] = next_path
|
461
|
+
when :lookahead
|
462
|
+
if !field_ast_nodes
|
463
|
+
field_ast_nodes = [ast_node]
|
464
|
+
end
|
465
|
+
|
466
|
+
extra_args[:lookahead] = Execution::Lookahead.new(
|
467
|
+
query: query,
|
468
|
+
ast_nodes: field_ast_nodes,
|
469
|
+
field: field_defn,
|
470
|
+
)
|
471
|
+
when :argument_details
|
472
|
+
# Use this flag to tell Interpreter::Arguments to add itself
|
473
|
+
# to the keyword args hash _before_ freezing everything.
|
474
|
+
extra_args[:argument_details] = :__arguments_add_self
|
475
|
+
when :irep_node
|
476
|
+
# This is used by `__typename` in order to support the legacy runtime,
|
477
|
+
# but it has no use here (and it's always `nil`).
|
478
|
+
# Stop adding it here to avoid the overhead of `.merge_extras` below.
|
479
|
+
when :parent
|
480
|
+
extra_args[:parent] = parent_object
|
481
|
+
else
|
482
|
+
extra_args[extra] = field_defn.fetch_extra(extra, context)
|
187
483
|
end
|
188
|
-
kwarg_arguments[:lookahead] = Execution::Lookahead.new(
|
189
|
-
query: query,
|
190
|
-
ast_nodes: field_ast_nodes,
|
191
|
-
field: field_defn,
|
192
|
-
)
|
193
|
-
else
|
194
|
-
kwarg_arguments[extra] = field_defn.fetch_extra(extra, context)
|
195
484
|
end
|
485
|
+
if extra_args.any?
|
486
|
+
resolved_arguments = resolved_arguments.merge_extras(extra_args)
|
487
|
+
end
|
488
|
+
resolved_arguments.keyword_arguments
|
196
489
|
end
|
197
490
|
|
491
|
+
set_all_interpreter_context(nil, nil, resolved_arguments, nil)
|
492
|
+
|
198
493
|
# Optimize for the case that field is selected only once
|
199
494
|
if field_ast_nodes.nil? || field_ast_nodes.size == 1
|
200
495
|
next_selections = ast_node.selections
|
496
|
+
directives = ast_node.directives
|
201
497
|
else
|
202
498
|
next_selections = []
|
203
|
-
|
499
|
+
directives = []
|
500
|
+
field_ast_nodes.each { |f|
|
501
|
+
next_selections.concat(f.selections)
|
502
|
+
directives.concat(f.directives)
|
503
|
+
}
|
204
504
|
end
|
205
505
|
|
206
|
-
field_result =
|
506
|
+
field_result = call_method_on_directives(:resolve, object, directives) do
|
207
507
|
# Actually call the field resolver and capture the result
|
208
|
-
app_result =
|
209
|
-
|
508
|
+
app_result = begin
|
509
|
+
query.with_error_handling do
|
510
|
+
query.trace("execute_field", {owner: owner_type, field: field_defn, path: next_path, ast_node: ast_node, query: query, object: object, arguments: kwarg_arguments}) do
|
511
|
+
field_defn.resolve(object, kwarg_arguments, context)
|
512
|
+
end
|
513
|
+
end
|
514
|
+
rescue GraphQL::ExecutionError => err
|
515
|
+
err
|
210
516
|
end
|
211
|
-
after_lazy(app_result, owner: owner_type, field: field_defn, path: next_path) do |inner_result|
|
212
|
-
continue_value = continue_value(next_path, inner_result, field_defn, return_type.non_null?, ast_node)
|
517
|
+
after_lazy(app_result, owner: owner_type, field: field_defn, path: next_path, ast_node: ast_node, scoped_context: context.scoped_context, owner_object: object, arguments: resolved_arguments, result_name: result_name, result: selection_result) do |inner_result|
|
518
|
+
continue_value = continue_value(next_path, inner_result, owner_type, field_defn, return_type.non_null?, ast_node, result_name, selection_result)
|
213
519
|
if HALT != continue_value
|
214
|
-
continue_field(next_path, continue_value, field_defn, return_type, ast_node, next_selections, false)
|
520
|
+
continue_field(next_path, continue_value, owner_type, field_defn, return_type, ast_node, next_selections, false, object, resolved_arguments, result_name, selection_result)
|
215
521
|
end
|
216
522
|
end
|
217
523
|
end
|
@@ -219,47 +525,144 @@ module GraphQL
|
|
219
525
|
# If this field is a root mutation field, immediately resolve
|
220
526
|
# all of its child fields before moving on to the next root mutation field.
|
221
527
|
# (Subselections of this mutation will still be resolved level-by-level.)
|
222
|
-
if
|
223
|
-
Interpreter::Resolve.resolve_all([field_result])
|
528
|
+
if is_eager_field
|
529
|
+
Interpreter::Resolve.resolve_all([field_result], @dataloader)
|
224
530
|
else
|
531
|
+
# Return this from `after_lazy` because it might be another lazy that needs to be resolved
|
225
532
|
field_result
|
226
533
|
end
|
227
534
|
end
|
228
535
|
end
|
229
536
|
|
537
|
+
def dead_result?(selection_result)
|
538
|
+
selection_result.graphql_dead || ((parent = selection_result.graphql_parent) && parent.graphql_dead)
|
539
|
+
end
|
540
|
+
|
541
|
+
def set_result(selection_result, result_name, value)
|
542
|
+
if !dead_result?(selection_result)
|
543
|
+
if value.nil? &&
|
544
|
+
( # there are two conditions under which `nil` is not allowed in the response:
|
545
|
+
(selection_result.graphql_non_null_list_items) || # this value would be written into a list that doesn't allow nils
|
546
|
+
((nn = selection_result.graphql_non_null_field_names) && nn.include?(result_name)) # this value would be written into a field that doesn't allow nils
|
547
|
+
)
|
548
|
+
# This is an invalid nil that should be propagated
|
549
|
+
# One caller of this method passes a block,
|
550
|
+
# namely when application code returns a `nil` to GraphQL and it doesn't belong there.
|
551
|
+
# The other possibility for reaching here is when a field returns an ExecutionError, so we write
|
552
|
+
# `nil` to the response, not knowing whether it's an invalid `nil` or not.
|
553
|
+
# (And in that case, we don't have to call the schema's handler, since it's not a bug in the application.)
|
554
|
+
# TODO the code is trying to tell me something.
|
555
|
+
yield if block_given?
|
556
|
+
parent = selection_result.graphql_parent
|
557
|
+
name_in_parent = selection_result.graphql_result_name
|
558
|
+
if parent.nil? # This is a top-level result hash
|
559
|
+
@response = nil
|
560
|
+
else
|
561
|
+
set_result(parent, name_in_parent, nil)
|
562
|
+
set_graphql_dead(selection_result)
|
563
|
+
end
|
564
|
+
else
|
565
|
+
selection_result[result_name] = value
|
566
|
+
end
|
567
|
+
end
|
568
|
+
end
|
569
|
+
|
570
|
+
# Mark this node and any already-registered children as dead,
|
571
|
+
# so that it accepts no more writes.
|
572
|
+
def set_graphql_dead(selection_result)
|
573
|
+
case selection_result
|
574
|
+
when GraphQLResultArray
|
575
|
+
selection_result.graphql_dead = true
|
576
|
+
selection_result.values.each { |v| set_graphql_dead(v) }
|
577
|
+
when GraphQLResultHash
|
578
|
+
selection_result.graphql_dead = true
|
579
|
+
selection_result.each { |k, v| set_graphql_dead(v) }
|
580
|
+
else
|
581
|
+
# It's a scalar, no way to mark it dead.
|
582
|
+
end
|
583
|
+
end
|
584
|
+
|
230
585
|
HALT = Object.new
|
231
|
-
def continue_value(path, value, field, is_non_null, ast_node)
|
232
|
-
|
586
|
+
def continue_value(path, value, parent_type, field, is_non_null, ast_node, result_name, selection_result) # rubocop:disable Metrics/ParameterLists
|
587
|
+
case value
|
588
|
+
when nil
|
233
589
|
if is_non_null
|
234
|
-
|
235
|
-
|
590
|
+
set_result(selection_result, result_name, nil) do
|
591
|
+
# This block is called if `result_name` is not dead. (Maybe a previous invalid nil caused it be marked dead.)
|
592
|
+
err = parent_type::InvalidNullError.new(parent_type, field, value)
|
593
|
+
schema.type_error(err, context)
|
594
|
+
end
|
236
595
|
else
|
237
|
-
|
596
|
+
set_result(selection_result, result_name, nil)
|
238
597
|
end
|
239
598
|
HALT
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
599
|
+
when GraphQL::Error
|
600
|
+
# Handle these cases inside a single `when`
|
601
|
+
# to avoid the overhead of checking three different classes
|
602
|
+
# every time.
|
603
|
+
if value.is_a?(GraphQL::ExecutionError)
|
604
|
+
if selection_result.nil? || !dead_result?(selection_result)
|
605
|
+
value.path ||= path
|
606
|
+
value.ast_node ||= ast_node
|
607
|
+
context.errors << value
|
608
|
+
if selection_result
|
609
|
+
set_result(selection_result, result_name, nil)
|
610
|
+
end
|
611
|
+
end
|
612
|
+
HALT
|
613
|
+
elsif value.is_a?(GraphQL::UnauthorizedError)
|
614
|
+
# this hook might raise & crash, or it might return
|
615
|
+
# a replacement value
|
616
|
+
next_value = begin
|
617
|
+
schema.unauthorized_object(value)
|
618
|
+
rescue GraphQL::ExecutionError => err
|
619
|
+
err
|
620
|
+
end
|
621
|
+
continue_value(path, next_value, parent_type, field, is_non_null, ast_node, result_name, selection_result)
|
622
|
+
elsif GraphQL::Execution::Execute::SKIP == value
|
623
|
+
# It's possible a lazy was already written here
|
624
|
+
case selection_result
|
625
|
+
when GraphQLResultHash
|
626
|
+
selection_result.delete(result_name)
|
627
|
+
when GraphQLResultArray
|
628
|
+
selection_result.graphql_skip_at(result_name)
|
629
|
+
when nil
|
630
|
+
# this can happen with directives
|
631
|
+
else
|
632
|
+
raise "Invariant: unexpected result class #{selection_result.class} (#{selection_result.inspect})"
|
633
|
+
end
|
634
|
+
HALT
|
635
|
+
else
|
636
|
+
# What could this actually _be_? Anyhow,
|
637
|
+
# preserve the default behavior of doing nothing with it.
|
638
|
+
value
|
249
639
|
end
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
640
|
+
when Array
|
641
|
+
# It's an array full of execution errors; add them all.
|
642
|
+
if value.any? && value.all? { |v| v.is_a?(GraphQL::ExecutionError) }
|
643
|
+
list_type_at_all = (field && (field.type.list?))
|
644
|
+
if selection_result.nil? || !dead_result?(selection_result)
|
645
|
+
value.each_with_index do |error, index|
|
646
|
+
error.ast_node ||= ast_node
|
647
|
+
error.path ||= path + (list_type_at_all ? [index] : [])
|
648
|
+
context.errors << error
|
649
|
+
end
|
650
|
+
if selection_result
|
651
|
+
if list_type_at_all
|
652
|
+
result_without_errors = value.map { |v| v.is_a?(GraphQL::ExecutionError) ? nil : v }
|
653
|
+
set_result(selection_result, result_name, result_without_errors)
|
654
|
+
else
|
655
|
+
set_result(selection_result, result_name, nil)
|
656
|
+
end
|
657
|
+
end
|
658
|
+
end
|
659
|
+
HALT
|
660
|
+
else
|
661
|
+
value
|
259
662
|
end
|
260
|
-
|
261
|
-
|
262
|
-
|
663
|
+
when GraphQL::Execution::Interpreter::RawValue
|
664
|
+
# Write raw value directly to the response without resolving nested objects
|
665
|
+
set_result(selection_result, result_name, value.resolve)
|
263
666
|
HALT
|
264
667
|
else
|
265
668
|
value
|
@@ -274,92 +677,169 @@ module GraphQL
|
|
274
677
|
# Location information from `path` and `ast_node`.
|
275
678
|
#
|
276
679
|
# @return [Lazy, Array, Hash, Object] Lazy, Array, and Hash are all traversed to resolve lazy values later
|
277
|
-
def continue_field(path, value, field,
|
278
|
-
|
680
|
+
def continue_field(path, value, owner_type, field, current_type, ast_node, next_selections, is_non_null, owner_object, arguments, result_name, selection_result) # rubocop:disable Metrics/ParameterLists
|
681
|
+
if current_type.non_null?
|
682
|
+
current_type = current_type.of_type
|
683
|
+
is_non_null = true
|
684
|
+
end
|
685
|
+
|
686
|
+
case current_type.kind.name
|
279
687
|
when "SCALAR", "ENUM"
|
280
|
-
r =
|
281
|
-
|
688
|
+
r = current_type.coerce_result(value, context)
|
689
|
+
set_result(selection_result, result_name, r)
|
282
690
|
r
|
283
691
|
when "UNION", "INTERFACE"
|
284
|
-
resolved_type_or_lazy =
|
285
|
-
|
286
|
-
|
692
|
+
resolved_type_or_lazy, resolved_value = resolve_type(current_type, value, path)
|
693
|
+
resolved_value ||= value
|
694
|
+
|
695
|
+
after_lazy(resolved_type_or_lazy, owner: current_type, path: path, ast_node: ast_node, scoped_context: context.scoped_context, field: field, owner_object: owner_object, arguments: arguments, trace: false, result_name: result_name, result: selection_result) do |resolved_type|
|
696
|
+
possible_types = query.possible_types(current_type)
|
287
697
|
|
288
698
|
if !possible_types.include?(resolved_type)
|
289
|
-
parent_type = field.
|
290
|
-
|
699
|
+
parent_type = field.owner_type
|
700
|
+
err_class = current_type::UnresolvedTypeError
|
701
|
+
type_error = err_class.new(resolved_value, field, parent_type, resolved_type, possible_types)
|
291
702
|
schema.type_error(type_error, context)
|
292
|
-
|
703
|
+
set_result(selection_result, result_name, nil)
|
293
704
|
nil
|
294
705
|
else
|
295
|
-
resolved_type
|
296
|
-
continue_field(path, value, field, resolved_type, ast_node, next_selections, is_non_null)
|
706
|
+
continue_field(path, resolved_value, owner_type, field, resolved_type, ast_node, next_selections, is_non_null, owner_object, arguments, result_name, selection_result)
|
297
707
|
end
|
298
708
|
end
|
299
709
|
when "OBJECT"
|
300
710
|
object_proxy = begin
|
301
|
-
|
711
|
+
authorized_new(current_type, value, context)
|
302
712
|
rescue GraphQL::ExecutionError => err
|
303
713
|
err
|
304
714
|
end
|
305
|
-
after_lazy(object_proxy, owner:
|
306
|
-
continue_value = continue_value(path, inner_object, field, is_non_null, ast_node)
|
715
|
+
after_lazy(object_proxy, owner: current_type, path: path, ast_node: ast_node, scoped_context: context.scoped_context, field: field, owner_object: owner_object, arguments: arguments, trace: false, result_name: result_name, result: selection_result) do |inner_object|
|
716
|
+
continue_value = continue_value(path, inner_object, owner_type, field, is_non_null, ast_node, result_name, selection_result)
|
307
717
|
if HALT != continue_value
|
308
|
-
response_hash =
|
309
|
-
|
310
|
-
|
311
|
-
|
718
|
+
response_hash = GraphQLResultHash.new(result_name, selection_result)
|
719
|
+
set_result(selection_result, result_name, response_hash)
|
720
|
+
gathered_selections = gather_selections(continue_value, current_type, next_selections)
|
721
|
+
# There are two possibilities for `gathered_selections`:
|
722
|
+
# 1. All selections of this object should be evaluated together (there are no runtime directives modifying execution).
|
723
|
+
# This case is handled below, and the result can be written right into the main `response_hash` above.
|
724
|
+
# In this case, `gathered_selections` is a hash of selections.
|
725
|
+
# 2. Some selections of this object have runtime directives that may or may not modify execution.
|
726
|
+
# That part of the selection is evaluated in an isolated way, writing into a sub-response object which is
|
727
|
+
# eventually merged into the final response. In this case, `gathered_selections` is an array of things to run in isolation.
|
728
|
+
# (Technically, it's possible that one of those entries _doesn't_ require isolation.)
|
729
|
+
tap_or_each(gathered_selections) do |selections, is_selection_array|
|
730
|
+
if is_selection_array
|
731
|
+
this_result = GraphQLResultHash.new(result_name, selection_result)
|
732
|
+
final_result = response_hash
|
733
|
+
else
|
734
|
+
this_result = response_hash
|
735
|
+
final_result = nil
|
736
|
+
end
|
737
|
+
set_all_interpreter_context(continue_value, nil, nil, path) # reset this mutable state
|
738
|
+
call_method_on_directives(:resolve, continue_value, selections.graphql_directives) do
|
739
|
+
evaluate_selections(
|
740
|
+
path,
|
741
|
+
context.scoped_context,
|
742
|
+
continue_value,
|
743
|
+
current_type,
|
744
|
+
false,
|
745
|
+
selections,
|
746
|
+
this_result,
|
747
|
+
final_result,
|
748
|
+
owner_object.object,
|
749
|
+
)
|
750
|
+
this_result
|
751
|
+
end
|
752
|
+
end
|
312
753
|
end
|
313
754
|
end
|
314
755
|
when "LIST"
|
315
|
-
|
316
|
-
|
317
|
-
|
756
|
+
inner_type = current_type.of_type
|
757
|
+
# This is true for objects, unions, and interfaces
|
758
|
+
use_dataloader_job = !inner_type.unwrap.kind.input?
|
759
|
+
response_list = GraphQLResultArray.new(result_name, selection_result)
|
760
|
+
response_list.graphql_non_null_list_items = inner_type.non_null?
|
761
|
+
set_result(selection_result, result_name, response_list)
|
762
|
+
|
318
763
|
idx = 0
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
764
|
+
scoped_context = context.scoped_context
|
765
|
+
begin
|
766
|
+
value.each do |inner_value|
|
767
|
+
break if dead_result?(response_list)
|
768
|
+
next_path = path.dup
|
769
|
+
next_path << idx
|
770
|
+
this_idx = idx
|
771
|
+
next_path.freeze
|
772
|
+
idx += 1
|
773
|
+
if use_dataloader_job
|
774
|
+
@dataloader.append_job do
|
775
|
+
resolve_list_item(inner_value, inner_type, next_path, ast_node, scoped_context, field, owner_object, arguments, this_idx, response_list, next_selections, owner_type)
|
776
|
+
end
|
777
|
+
else
|
778
|
+
resolve_list_item(inner_value, inner_type, next_path, ast_node, scoped_context, field, owner_object, arguments, this_idx, response_list, next_selections, owner_type)
|
331
779
|
end
|
332
780
|
end
|
781
|
+
rescue NoMethodError => err
|
782
|
+
# Ruby 2.2 doesn't have NoMethodError#receiver, can't check that one in this case. (It's been EOL since 2017.)
|
783
|
+
if err.name == :each && (err.respond_to?(:receiver) ? err.receiver == value : true)
|
784
|
+
# This happens when the GraphQL schema doesn't match the implementation. Help the dev debug.
|
785
|
+
raise ListResultFailedError.new(value: value, field: field, path: path)
|
786
|
+
else
|
787
|
+
# This was some other NoMethodError -- let it bubble to reveal the real error.
|
788
|
+
raise
|
789
|
+
end
|
333
790
|
end
|
791
|
+
|
334
792
|
response_list
|
335
|
-
when "NON_NULL"
|
336
|
-
inner_type = type.of_type
|
337
|
-
# For fields like `__schema: __Schema!`
|
338
|
-
inner_type = resolve_if_late_bound_type(inner_type)
|
339
|
-
# Don't `set_type_at_path` because we want the static type,
|
340
|
-
# we're going to use that to determine whether a `nil` should be propagated or not.
|
341
|
-
continue_field(path, value, field, inner_type, ast_node, next_selections, true)
|
342
793
|
else
|
343
|
-
raise "Invariant: Unhandled type kind #{
|
794
|
+
raise "Invariant: Unhandled type kind #{current_type.kind} (#{current_type})"
|
795
|
+
end
|
796
|
+
end
|
797
|
+
|
798
|
+
def resolve_list_item(inner_value, inner_type, next_path, ast_node, scoped_context, field, owner_object, arguments, this_idx, response_list, next_selections, owner_type) # rubocop:disable Metrics/ParameterLists
|
799
|
+
set_all_interpreter_context(nil, nil, nil, next_path)
|
800
|
+
call_method_on_directives(:resolve_each, owner_object, ast_node.directives) do
|
801
|
+
# This will update `response_list` with the lazy
|
802
|
+
after_lazy(inner_value, owner: inner_type, path: next_path, ast_node: ast_node, scoped_context: scoped_context, field: field, owner_object: owner_object, arguments: arguments, result_name: this_idx, result: response_list) do |inner_inner_value|
|
803
|
+
continue_value = continue_value(next_path, inner_inner_value, owner_type, field, inner_type.non_null?, ast_node, this_idx, response_list)
|
804
|
+
if HALT != continue_value
|
805
|
+
continue_field(next_path, continue_value, owner_type, field, inner_type, ast_node, next_selections, false, owner_object, arguments, this_idx, response_list)
|
806
|
+
end
|
807
|
+
end
|
344
808
|
end
|
345
809
|
end
|
346
810
|
|
347
|
-
def
|
348
|
-
|
811
|
+
def call_method_on_directives(method_name, object, directives, &block)
|
812
|
+
return yield if directives.nil? || directives.empty?
|
813
|
+
run_directive(method_name, object, directives, 0, &block)
|
349
814
|
end
|
350
815
|
|
351
|
-
def run_directive(object,
|
352
|
-
dir_node =
|
816
|
+
def run_directive(method_name, object, directives, idx, &block)
|
817
|
+
dir_node = directives[idx]
|
353
818
|
if !dir_node
|
354
819
|
yield
|
355
820
|
else
|
356
|
-
dir_defn =
|
821
|
+
dir_defn = @schema_directives.fetch(dir_node.name)
|
357
822
|
if !dir_defn.is_a?(Class)
|
358
|
-
dir_defn = dir_defn.
|
359
|
-
end
|
360
|
-
|
361
|
-
|
362
|
-
|
823
|
+
dir_defn = dir_defn.type_class || raise("Only class-based directives are supported (not `@#{dir_node.name}`)")
|
824
|
+
end
|
825
|
+
raw_dir_args = arguments(nil, dir_defn, dir_node)
|
826
|
+
dir_args = continue_value(
|
827
|
+
@context[:current_path], # path
|
828
|
+
raw_dir_args, # value
|
829
|
+
dir_defn, # parent_type
|
830
|
+
nil, # field
|
831
|
+
false, # is_non_null
|
832
|
+
dir_node, # ast_node
|
833
|
+
nil, # result_name
|
834
|
+
nil, # selection_result
|
835
|
+
)
|
836
|
+
|
837
|
+
if dir_args == HALT
|
838
|
+
nil
|
839
|
+
else
|
840
|
+
dir_defn.public_send(method_name, object, dir_args, context) do
|
841
|
+
run_directive(method_name, object, directives, idx + 1, &block)
|
842
|
+
end
|
363
843
|
end
|
364
844
|
end
|
365
845
|
end
|
@@ -367,7 +847,7 @@ module GraphQL
|
|
367
847
|
# Check {Schema::Directive.include?} for each directive that's present
|
368
848
|
def directives_include?(node, graphql_object, parent_type)
|
369
849
|
node.directives.each do |dir_node|
|
370
|
-
dir_defn =
|
850
|
+
dir_defn = @schema_directives.fetch(dir_node.name).type_class || raise("Only class-based directives are supported (not #{dir_node.name.inspect})")
|
371
851
|
args = arguments(graphql_object, dir_defn, dir_node)
|
372
852
|
if !dir_defn.include?(graphql_object, args, context)
|
373
853
|
return false
|
@@ -376,11 +856,18 @@ module GraphQL
|
|
376
856
|
true
|
377
857
|
end
|
378
858
|
|
379
|
-
def
|
380
|
-
if
|
381
|
-
|
382
|
-
|
383
|
-
|
859
|
+
def set_all_interpreter_context(object, field, arguments, path)
|
860
|
+
if object
|
861
|
+
@context[:current_object] = @interpreter_context[:current_object] = object
|
862
|
+
end
|
863
|
+
if field
|
864
|
+
@context[:current_field] = @interpreter_context[:current_field] = field
|
865
|
+
end
|
866
|
+
if arguments
|
867
|
+
@context[:current_arguments] = @interpreter_context[:current_arguments] = arguments
|
868
|
+
end
|
869
|
+
if path
|
870
|
+
@context[:current_path] = @interpreter_context[:current_path] = path
|
384
871
|
end
|
385
872
|
end
|
386
873
|
|
@@ -388,219 +875,93 @@ module GraphQL
|
|
388
875
|
# @param path [Array<String>]
|
389
876
|
# @param field [GraphQL::Schema::Field]
|
390
877
|
# @param eager [Boolean] Set to `true` for mutation root fields only
|
878
|
+
# @param trace [Boolean] If `false`, don't wrap this with field tracing
|
391
879
|
# @return [GraphQL::Execution::Lazy, Object] If loading `object` will be deferred, it's a wrapper over it.
|
392
|
-
def after_lazy(
|
393
|
-
|
394
|
-
@interpreter_context[:current_field] = field
|
395
|
-
if schema.lazy?(obj)
|
880
|
+
def after_lazy(lazy_obj, owner:, field:, path:, scoped_context:, owner_object:, arguments:, ast_node:, result:, result_name:, eager: false, trace: true, &block)
|
881
|
+
if lazy?(lazy_obj)
|
396
882
|
lazy = GraphQL::Execution::Lazy.new(path: path, field: field) do
|
397
|
-
|
398
|
-
|
883
|
+
set_all_interpreter_context(owner_object, field, arguments, path)
|
884
|
+
context.scoped_context = scoped_context
|
399
885
|
# Wrap the execution of _this_ method with tracing,
|
400
886
|
# but don't wrap the continuation below
|
401
|
-
inner_obj =
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
887
|
+
inner_obj = begin
|
888
|
+
query.with_error_handling do
|
889
|
+
begin
|
890
|
+
if trace
|
891
|
+
query.trace("execute_field_lazy", {owner: owner, field: field, path: path, query: query, object: owner_object, arguments: arguments, ast_node: ast_node}) do
|
892
|
+
schema.sync_lazy(lazy_obj)
|
893
|
+
end
|
894
|
+
else
|
895
|
+
schema.sync_lazy(lazy_obj)
|
896
|
+
end
|
897
|
+
rescue GraphQL::ExecutionError, GraphQL::UnauthorizedError => err
|
898
|
+
err
|
899
|
+
end
|
406
900
|
end
|
901
|
+
rescue GraphQL::ExecutionError => ex_err
|
902
|
+
ex_err
|
407
903
|
end
|
408
|
-
|
409
|
-
yield(really_inner_obj)
|
410
|
-
end
|
904
|
+
yield(inner_obj)
|
411
905
|
end
|
412
906
|
|
413
907
|
if eager
|
414
908
|
lazy.value
|
415
909
|
else
|
416
|
-
|
910
|
+
set_result(result, result_name, lazy)
|
417
911
|
lazy
|
418
912
|
end
|
419
913
|
else
|
420
|
-
|
914
|
+
set_all_interpreter_context(owner_object, field, arguments, path)
|
915
|
+
yield(lazy_obj)
|
421
916
|
end
|
422
917
|
end
|
423
918
|
|
424
|
-
def
|
425
|
-
|
426
|
-
|
427
|
-
ast_args_or_hash.arguments.each do |arg|
|
428
|
-
yield(arg.name, arg.value)
|
429
|
-
end
|
430
|
-
when Hash
|
431
|
-
ast_args_or_hash.each do |key, value|
|
432
|
-
normalized_name = GraphQL::Schema::Member::BuildType.camelize(key.to_s)
|
433
|
-
yield(normalized_name, value)
|
434
|
-
end
|
919
|
+
def arguments(graphql_object, arg_owner, ast_node)
|
920
|
+
if arg_owner.arguments_statically_coercible?
|
921
|
+
query.arguments_for(ast_node, arg_owner)
|
435
922
|
else
|
436
|
-
|
923
|
+
# The arguments must be prepared in the context of the given object
|
924
|
+
query.arguments_for(ast_node, arg_owner, parent_object: graphql_object)
|
437
925
|
end
|
438
926
|
end
|
439
927
|
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
# Need to distinguish between client-provided `nil`
|
446
|
-
# and nothing-at-all
|
447
|
-
is_present, value = arg_to_value(graphql_object, arg_defn.type, arg_value)
|
448
|
-
if is_present
|
449
|
-
# This doesn't apply to directives, which are legacy
|
450
|
-
# Can remove this when Skip and Include use classes or something.
|
451
|
-
if graphql_object
|
452
|
-
value = arg_defn.prepare_value(graphql_object, value)
|
453
|
-
end
|
454
|
-
kwarg_arguments[arg_defn.keyword] = value
|
455
|
-
end
|
456
|
-
end
|
457
|
-
arg_defns.each do |name, arg_defn|
|
458
|
-
if arg_defn.default_value? && !kwarg_arguments.key?(arg_defn.keyword)
|
459
|
-
_is_present, value = arg_to_value(graphql_object, arg_defn.type, arg_defn.default_value)
|
460
|
-
kwarg_arguments[arg_defn.keyword] = value
|
461
|
-
end
|
462
|
-
end
|
463
|
-
kwarg_arguments
|
928
|
+
# Set this pair in the Query context, but also in the interpeter namespace,
|
929
|
+
# for compatibility.
|
930
|
+
def set_interpreter_context(key, value)
|
931
|
+
@interpreter_context[key] = value
|
932
|
+
@context[key] = value
|
464
933
|
end
|
465
934
|
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
# @param ast_value [GraphQL::Language::Nodes::VariableIdentifier, String, Integer, Float, Boolean]
|
470
|
-
# @return [Array(is_present, value)]
|
471
|
-
def arg_to_value(graphql_object, arg_type, ast_value)
|
472
|
-
if ast_value.is_a?(GraphQL::Language::Nodes::VariableIdentifier)
|
473
|
-
# If it's not here, it will get added later
|
474
|
-
if query.variables.key?(ast_value.name)
|
475
|
-
return true, query.variables[ast_value.name]
|
476
|
-
else
|
477
|
-
return false, nil
|
478
|
-
end
|
479
|
-
elsif ast_value.is_a?(GraphQL::Language::Nodes::NullValue)
|
480
|
-
return true, nil
|
481
|
-
elsif arg_type.is_a?(GraphQL::Schema::NonNull)
|
482
|
-
arg_to_value(graphql_object, arg_type.of_type, ast_value)
|
483
|
-
elsif arg_type.is_a?(GraphQL::Schema::List)
|
484
|
-
# Treat a single value like a list
|
485
|
-
arg_value = Array(ast_value)
|
486
|
-
list = []
|
487
|
-
arg_value.map do |inner_v|
|
488
|
-
_present, value = arg_to_value(graphql_object, arg_type.of_type, inner_v)
|
489
|
-
list << value
|
490
|
-
end
|
491
|
-
return true, list
|
492
|
-
elsif arg_type.is_a?(Class) && arg_type < GraphQL::Schema::InputObject
|
493
|
-
# For these, `prepare` is applied during `#initialize`.
|
494
|
-
# Pass `nil` so it will be skipped in `#arguments`.
|
495
|
-
# What a mess.
|
496
|
-
args = arguments(nil, arg_type, ast_value)
|
497
|
-
# We're not tracking defaults_used, but for our purposes
|
498
|
-
# we compare the value to the default value.
|
499
|
-
return true, arg_type.new(ruby_kwargs: args, context: context, defaults_used: nil)
|
500
|
-
else
|
501
|
-
flat_value = flatten_ast_value(ast_value)
|
502
|
-
return true, arg_type.coerce_input(flat_value, context)
|
503
|
-
end
|
935
|
+
def delete_interpreter_context(key)
|
936
|
+
@interpreter_context.delete(key)
|
937
|
+
@context.delete(key)
|
504
938
|
end
|
505
939
|
|
506
|
-
def
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
when GraphQL::Language::Nodes::InputObject
|
511
|
-
h = {}
|
512
|
-
v.arguments.each do |arg|
|
513
|
-
h[arg.name] = flatten_ast_value(arg.value)
|
514
|
-
end
|
515
|
-
h
|
516
|
-
when Array
|
517
|
-
v.map { |v2| flatten_ast_value(v2) }
|
518
|
-
when GraphQL::Language::Nodes::VariableIdentifier
|
519
|
-
flatten_ast_value(query.variables[v.name])
|
520
|
-
else
|
521
|
-
v
|
940
|
+
def resolve_type(type, value, path)
|
941
|
+
trace_payload = { context: context, type: type, object: value, path: path }
|
942
|
+
resolved_type, resolved_value = query.trace("resolve_type", trace_payload) do
|
943
|
+
query.resolve_type(type, value)
|
522
944
|
end
|
523
|
-
end
|
524
|
-
|
525
|
-
def write_invalid_null_in_response(path, invalid_null_error)
|
526
|
-
if !dead_path?(path)
|
527
|
-
schema.type_error(invalid_null_error, context)
|
528
|
-
write_in_response(path, nil)
|
529
|
-
add_dead_path(path)
|
530
|
-
end
|
531
|
-
end
|
532
945
|
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
946
|
+
if lazy?(resolved_type)
|
947
|
+
GraphQL::Execution::Lazy.new do
|
948
|
+
query.trace("resolve_type_lazy", trace_payload) do
|
949
|
+
schema.sync_lazy(resolved_type)
|
950
|
+
end
|
537
951
|
end
|
538
|
-
write_in_response(path, nil)
|
539
|
-
add_dead_path(path)
|
540
|
-
end
|
541
|
-
end
|
542
|
-
|
543
|
-
def write_in_response(path, value)
|
544
|
-
if dead_path?(path)
|
545
|
-
return
|
546
952
|
else
|
547
|
-
|
548
|
-
# This nil is invalid, try writing it at the previous spot
|
549
|
-
propagate_path = path[0..-2]
|
550
|
-
write_in_response(propagate_path, value)
|
551
|
-
add_dead_path(propagate_path)
|
552
|
-
else
|
553
|
-
@response.write(path, value)
|
554
|
-
end
|
953
|
+
[resolved_type, resolved_value]
|
555
954
|
end
|
556
955
|
end
|
557
956
|
|
558
|
-
|
559
|
-
|
560
|
-
# This hash matches the response
|
561
|
-
def type_at(path)
|
562
|
-
t = @types_at_paths
|
563
|
-
path.each do |part|
|
564
|
-
t = t[part] || (raise("Invariant: #{part.inspect} not found in #{t}"))
|
565
|
-
end
|
566
|
-
t = t[:__type]
|
567
|
-
t
|
568
|
-
end
|
569
|
-
|
570
|
-
def set_type_at_path(path, type)
|
571
|
-
types = @types_at_paths
|
572
|
-
path.each do |part|
|
573
|
-
types = types[part] ||= {}
|
574
|
-
end
|
575
|
-
# Use this magic key so that the hash contains:
|
576
|
-
# - string keys for nested fields
|
577
|
-
# - :__type for the object type of a selection
|
578
|
-
types[:__type] ||= type
|
579
|
-
nil
|
580
|
-
end
|
581
|
-
|
582
|
-
# Mark `path` as having been permanently nulled out.
|
583
|
-
# No values will be added beyond that path.
|
584
|
-
def add_dead_path(path)
|
585
|
-
dead = @dead_paths
|
586
|
-
path.each do |part|
|
587
|
-
dead = dead[part] ||= {}
|
588
|
-
end
|
589
|
-
dead[:__dead] = true
|
957
|
+
def authorized_new(type, value, context)
|
958
|
+
type.authorized_new(value, context)
|
590
959
|
end
|
591
960
|
|
592
|
-
def
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
if res[:__dead]
|
597
|
-
break
|
598
|
-
else
|
599
|
-
res = res[part]
|
600
|
-
end
|
601
|
-
end
|
602
|
-
end
|
603
|
-
res && res[:__dead]
|
961
|
+
def lazy?(object)
|
962
|
+
@lazy_cache.fetch(object.class) {
|
963
|
+
@lazy_cache[object.class] = @schema.lazy?(object)
|
964
|
+
}
|
604
965
|
end
|
605
966
|
end
|
606
967
|
end
|