graphql 1.12.12 → 2.2.14
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 +4 -4
- data/lib/generators/graphql/core.rb +3 -8
- 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/{templates → install/templates}/base_mutation.erb +2 -0
- data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +2 -0
- data/lib/generators/graphql/install_generator.rb +14 -4
- data/lib/generators/graphql/interface_generator.rb +7 -7
- 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 +5 -30
- data/lib/generators/graphql/mutation_update_generator.rb +22 -0
- data/lib/generators/graphql/object_generator.rb +10 -38
- data/lib/generators/graphql/orm_mutations_base.rb +40 -0
- data/lib/generators/graphql/relay.rb +23 -12
- data/lib/generators/graphql/scalar_generator.rb +4 -2
- data/lib/generators/graphql/templates/base_argument.erb +2 -0
- data/lib/generators/graphql/templates/base_connection.erb +2 -0
- data/lib/generators/graphql/templates/base_edge.erb +2 -0
- data/lib/generators/graphql/templates/base_enum.erb +2 -0
- data/lib/generators/graphql/templates/base_field.erb +2 -0
- data/lib/generators/graphql/templates/base_input_object.erb +2 -0
- data/lib/generators/graphql/templates/base_interface.erb +2 -0
- data/lib/generators/graphql/templates/base_object.erb +2 -0
- data/lib/generators/graphql/templates/base_resolver.erb +6 -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 +5 -1
- data/lib/generators/graphql/templates/graphql_controller.erb +2 -0
- data/lib/generators/graphql/templates/input.erb +9 -0
- data/lib/generators/graphql/templates/interface.erb +4 -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 +2 -0
- data/lib/generators/graphql/templates/object.erb +4 -2
- data/lib/generators/graphql/templates/query_type.erb +2 -0
- data/lib/generators/graphql/templates/scalar.erb +3 -1
- data/lib/generators/graphql/templates/schema.erb +19 -2
- data/lib/generators/graphql/templates/union.erb +4 -2
- data/lib/generators/graphql/type_generator.rb +46 -10
- data/lib/generators/graphql/union_generator.rb +5 -5
- data/lib/graphql/analysis/ast/analyzer.rb +7 -0
- data/lib/graphql/analysis/ast/field_usage.rb +55 -1
- data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -1
- data/lib/graphql/analysis/ast/query_complexity.rb +88 -140
- data/lib/graphql/analysis/ast/query_depth.rb +7 -3
- data/lib/graphql/analysis/ast/visitor.rb +50 -42
- data/lib/graphql/analysis/ast.rb +26 -23
- data/lib/graphql/analysis.rb +0 -7
- data/lib/graphql/backtrace/table.rb +4 -22
- data/lib/graphql/backtrace/trace.rb +93 -0
- data/lib/graphql/backtrace/tracer.rb +8 -6
- data/lib/graphql/backtrace.rb +3 -8
- data/lib/graphql/coercion_error.rb +1 -9
- data/lib/graphql/dataloader/async_dataloader.rb +85 -0
- data/lib/graphql/dataloader/null_dataloader.rb +3 -1
- data/lib/graphql/dataloader/request.rb +5 -0
- data/lib/graphql/dataloader/source.rb +120 -31
- data/lib/graphql/dataloader.rb +168 -142
- data/lib/graphql/date_encoding_error.rb +16 -0
- data/lib/graphql/dig.rb +1 -1
- data/lib/graphql/duration_encoding_error.rb +16 -0
- data/lib/graphql/execution/errors.rb +12 -81
- data/lib/graphql/execution/interpreter/arguments.rb +2 -2
- data/lib/graphql/execution/interpreter/arguments_cache.rb +36 -34
- data/lib/graphql/execution/interpreter/resolve.rb +32 -2
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +170 -0
- data/lib/graphql/execution/interpreter/runtime.rb +414 -341
- data/lib/graphql/execution/interpreter.rb +122 -80
- data/lib/graphql/execution/lazy.rb +11 -21
- data/lib/graphql/execution/lookahead.rb +125 -54
- data/lib/graphql/execution/multiplex.rb +4 -172
- data/lib/graphql/execution.rb +11 -4
- data/lib/graphql/integer_encoding_error.rb +18 -2
- data/lib/graphql/introspection/directive_location_enum.rb +2 -2
- data/lib/graphql/introspection/directive_type.rb +5 -3
- data/lib/graphql/introspection/dynamic_fields.rb +3 -8
- data/lib/graphql/introspection/entry_points.rb +11 -18
- data/lib/graphql/introspection/enum_value_type.rb +2 -2
- data/lib/graphql/introspection/field_type.rb +3 -3
- data/lib/graphql/introspection/input_value_type.rb +10 -4
- data/lib/graphql/introspection/schema_type.rb +12 -5
- data/lib/graphql/introspection/type_type.rb +25 -12
- data/lib/graphql/introspection.rb +6 -2
- data/lib/graphql/language/block_string.rb +37 -25
- data/lib/graphql/language/definition_slice.rb +1 -1
- data/lib/graphql/language/document_from_schema_definition.rb +78 -65
- data/lib/graphql/language/lexer.rb +345 -1467
- data/lib/graphql/language/nodes.rb +145 -91
- data/lib/graphql/language/parser.rb +701 -1921
- data/lib/graphql/language/printer.rb +351 -155
- data/lib/graphql/language/sanitized_printer.rb +25 -27
- data/lib/graphql/language/static_visitor.rb +167 -0
- data/lib/graphql/language/token.rb +0 -4
- data/lib/graphql/language/visitor.rb +188 -141
- data/lib/graphql/language.rb +1 -0
- data/lib/graphql/load_application_object_failed_error.rb +5 -1
- data/lib/graphql/name_validator.rb +0 -4
- data/lib/graphql/pagination/active_record_relation_connection.rb +37 -8
- data/lib/graphql/pagination/array_connection.rb +8 -6
- data/lib/graphql/pagination/connection.rb +61 -7
- data/lib/graphql/pagination/connections.rb +22 -23
- data/lib/graphql/pagination/mongoid_relation_connection.rb +1 -2
- data/lib/graphql/pagination/relation_connection.rb +60 -28
- data/lib/graphql/query/context/scoped_context.rb +101 -0
- data/lib/graphql/query/context.rb +109 -189
- data/lib/graphql/query/input_validation_result.rb +10 -1
- data/lib/graphql/query/null_context.rb +14 -29
- data/lib/graphql/query/validation_pipeline.rb +15 -39
- data/lib/graphql/query/variable_validation_error.rb +2 -2
- data/lib/graphql/query/variables.rb +35 -17
- data/lib/graphql/query.rb +78 -65
- data/lib/graphql/railtie.rb +8 -109
- data/lib/graphql/rake_task/validate.rb +1 -1
- data/lib/graphql/rake_task.rb +30 -11
- data/lib/graphql/relay/range_add.rb +9 -16
- data/lib/graphql/relay.rb +0 -15
- 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/schema/addition.rb +78 -45
- data/lib/graphql/schema/always_visible.rb +10 -0
- data/lib/graphql/schema/argument.rb +134 -80
- data/lib/graphql/schema/base_64_encoder.rb +3 -5
- data/lib/graphql/schema/build_from_definition.rb +60 -38
- data/lib/graphql/schema/directive/feature.rb +1 -1
- data/lib/graphql/schema/directive/flagged.rb +2 -2
- data/lib/graphql/schema/directive/include.rb +1 -1
- data/lib/graphql/schema/directive/one_of.rb +24 -0
- data/lib/graphql/schema/directive/skip.rb +1 -1
- data/lib/graphql/schema/directive/specified_by.rb +14 -0
- data/lib/graphql/schema/directive/transform.rb +2 -2
- data/lib/graphql/schema/directive.rb +33 -21
- data/lib/graphql/schema/enum.rb +93 -46
- data/lib/graphql/schema/enum_value.rb +4 -21
- data/lib/graphql/schema/field/connection_extension.rb +6 -16
- data/lib/graphql/schema/field/scope_extension.rb +8 -1
- data/lib/graphql/schema/field.rb +432 -337
- data/lib/graphql/schema/field_extension.rb +86 -2
- data/lib/graphql/schema/find_inherited_value.rb +3 -7
- data/lib/graphql/schema/finder.rb +5 -5
- data/lib/graphql/schema/has_single_input_argument.rb +156 -0
- data/lib/graphql/schema/input_object.rb +88 -90
- data/lib/graphql/schema/interface.rb +19 -59
- data/lib/graphql/schema/introspection_system.rb +6 -9
- data/lib/graphql/schema/late_bound_type.rb +8 -2
- data/lib/graphql/schema/list.rb +18 -7
- data/lib/graphql/schema/loader.rb +3 -3
- data/lib/graphql/schema/member/base_dsl_methods.rb +18 -19
- data/lib/graphql/schema/member/build_type.rb +16 -13
- data/lib/graphql/schema/member/has_arguments.rb +288 -84
- data/lib/graphql/schema/member/has_ast_node.rb +12 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +3 -4
- data/lib/graphql/schema/member/has_directives.rb +81 -61
- data/lib/graphql/schema/member/has_fields.rb +149 -31
- data/lib/graphql/schema/member/has_interfaces.rb +143 -0
- data/lib/graphql/schema/member/has_validators.rb +32 -6
- data/lib/graphql/schema/member/relay_shortcuts.rb +47 -2
- data/lib/graphql/schema/member/scoped.rb +19 -0
- data/lib/graphql/schema/member/type_system_helpers.rb +17 -0
- data/lib/graphql/schema/member/validates_input.rb +6 -6
- data/lib/graphql/schema/member.rb +1 -6
- data/lib/graphql/schema/mutation.rb +0 -9
- data/lib/graphql/schema/non_null.rb +7 -7
- data/lib/graphql/schema/object.rb +30 -119
- data/lib/graphql/schema/printer.rb +23 -25
- data/lib/graphql/schema/relay_classic_mutation.rb +13 -90
- data/lib/graphql/schema/resolver/has_payload_type.rb +46 -11
- data/lib/graphql/schema/resolver.rb +101 -102
- data/lib/graphql/schema/scalar.rb +20 -21
- data/lib/graphql/schema/subscription.rb +45 -17
- data/lib/graphql/schema/timeout.rb +25 -29
- data/lib/graphql/schema/type_expression.rb +1 -1
- data/lib/graphql/schema/type_membership.rb +21 -4
- data/lib/graphql/schema/union.rb +15 -15
- data/lib/graphql/schema/unique_within_type.rb +1 -1
- 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 +3 -1
- data/lib/graphql/schema/validator/format_validator.rb +4 -5
- data/lib/graphql/schema/validator/inclusion_validator.rb +3 -1
- data/lib/graphql/schema/validator/length_validator.rb +5 -3
- data/lib/graphql/schema/validator/numericality_validator.rb +13 -2
- data/lib/graphql/schema/validator/required_validator.rb +29 -15
- data/lib/graphql/schema/validator.rb +35 -27
- data/lib/graphql/schema/warden.rb +259 -132
- data/lib/graphql/schema/wrapper.rb +0 -5
- data/lib/graphql/schema.rb +658 -989
- data/lib/graphql/static_validation/all_rules.rb +3 -1
- data/lib/graphql/static_validation/base_visitor.rb +14 -28
- data/lib/graphql/static_validation/definition_dependencies.rb +7 -2
- data/lib/graphql/static_validation/error.rb +3 -1
- data/lib/graphql/static_validation/literal_validator.rb +21 -4
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +1 -1
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +11 -5
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +13 -13
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +12 -4
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +54 -28
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -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 +4 -4
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +13 -7
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +13 -7
- data/lib/graphql/static_validation/validation_context.rb +16 -6
- data/lib/graphql/static_validation/validator.rb +11 -27
- data/lib/graphql/static_validation.rb +0 -3
- data/lib/graphql/string_encoding_error.rb +13 -3
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +46 -9
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +38 -1
- data/lib/graphql/subscriptions/event.rb +75 -37
- data/lib/graphql/subscriptions/serialize.rb +25 -3
- data/lib/graphql/subscriptions.rb +59 -47
- data/lib/graphql/testing/helpers.rb +129 -0
- data/lib/graphql/testing.rb +2 -0
- data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +6 -20
- data/lib/graphql/tracing/appoptics_trace.rb +251 -0
- data/lib/graphql/tracing/appoptics_tracing.rb +2 -2
- data/lib/graphql/tracing/appsignal_trace.rb +77 -0
- data/lib/graphql/tracing/appsignal_tracing.rb +15 -0
- data/lib/graphql/tracing/data_dog_trace.rb +183 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +25 -15
- data/lib/graphql/{execution/instrumentation.rb → tracing/legacy_hooks_trace.rb} +10 -28
- data/lib/graphql/tracing/legacy_trace.rb +69 -0
- data/lib/graphql/tracing/new_relic_trace.rb +75 -0
- data/lib/graphql/tracing/notifications_trace.rb +45 -0
- data/lib/graphql/tracing/notifications_tracing.rb +59 -0
- data/lib/graphql/tracing/platform_trace.rb +118 -0
- data/lib/graphql/tracing/platform_tracing.rb +46 -49
- data/lib/graphql/tracing/{prometheus_tracing → prometheus_trace}/graphql_collector.rb +4 -2
- data/lib/graphql/tracing/prometheus_trace.rb +89 -0
- data/lib/graphql/tracing/prometheus_tracing.rb +3 -3
- data/lib/graphql/tracing/scout_trace.rb +72 -0
- data/lib/graphql/tracing/sentry_trace.rb +112 -0
- data/lib/graphql/tracing/statsd_trace.rb +56 -0
- data/lib/graphql/tracing/trace.rb +76 -0
- data/lib/graphql/tracing.rb +20 -41
- data/lib/graphql/type_kinds.rb +6 -3
- data/lib/graphql/types/big_int.rb +5 -1
- data/lib/graphql/types/int.rb +1 -1
- data/lib/graphql/types/iso_8601_date.rb +17 -6
- data/lib/graphql/types/iso_8601_date_time.rb +12 -1
- data/lib/graphql/types/iso_8601_duration.rb +77 -0
- data/lib/graphql/types/relay/base_connection.rb +16 -6
- data/lib/graphql/types/relay/connection_behaviors.rb +82 -32
- data/lib/graphql/types/relay/edge_behaviors.rb +36 -7
- data/lib/graphql/types/relay/has_node_field.rb +2 -2
- data/lib/graphql/types/relay/has_nodes_field.rb +2 -2
- data/lib/graphql/types/relay/node_behaviors.rb +12 -2
- data/lib/graphql/types/relay/page_info_behaviors.rb +7 -2
- data/lib/graphql/types/relay.rb +0 -3
- data/lib/graphql/types/string.rb +2 -2
- data/lib/graphql/types.rb +1 -0
- data/lib/graphql/unauthorized_error.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +33 -95
- data/readme.md +13 -6
- metadata +102 -185
- data/lib/graphql/analysis/analyze_query.rb +0 -98
- data/lib/graphql/analysis/field_usage.rb +0 -45
- data/lib/graphql/analysis/max_query_complexity.rb +0 -26
- data/lib/graphql/analysis/max_query_depth.rb +0 -26
- data/lib/graphql/analysis/query_complexity.rb +0 -88
- data/lib/graphql/analysis/query_depth.rb +0 -43
- data/lib/graphql/analysis/reducer_state.rb +0 -48
- data/lib/graphql/argument.rb +0 -131
- data/lib/graphql/authorization.rb +0 -82
- data/lib/graphql/backtrace/legacy_tracer.rb +0 -56
- data/lib/graphql/backwards_compatibility.rb +0 -61
- data/lib/graphql/base_type.rb +0 -230
- data/lib/graphql/boolean_type.rb +0 -2
- data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
- data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
- data/lib/graphql/compatibility/execution_specification.rb +0 -436
- data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
- data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -215
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -87
- data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
- data/lib/graphql/compatibility/query_parser_specification.rb +0 -266
- data/lib/graphql/compatibility/schema_parser_specification.rb +0 -682
- data/lib/graphql/compatibility.rb +0 -5
- data/lib/graphql/define/assign_argument.rb +0 -12
- data/lib/graphql/define/assign_connection.rb +0 -13
- data/lib/graphql/define/assign_enum_value.rb +0 -18
- data/lib/graphql/define/assign_global_id_field.rb +0 -11
- data/lib/graphql/define/assign_mutation_function.rb +0 -34
- data/lib/graphql/define/assign_object_field.rb +0 -42
- data/lib/graphql/define/defined_object_proxy.rb +0 -53
- data/lib/graphql/define/instance_definable.rb +0 -240
- data/lib/graphql/define/no_definition_error.rb +0 -7
- data/lib/graphql/define/non_null_with_bang.rb +0 -16
- data/lib/graphql/define/type_definer.rb +0 -31
- data/lib/graphql/define.rb +0 -31
- data/lib/graphql/deprecated_dsl.rb +0 -47
- data/lib/graphql/deprecation.rb +0 -13
- data/lib/graphql/directive/deprecated_directive.rb +0 -2
- data/lib/graphql/directive/include_directive.rb +0 -2
- data/lib/graphql/directive/skip_directive.rb +0 -2
- data/lib/graphql/directive.rb +0 -111
- data/lib/graphql/enum_type.rb +0 -129
- data/lib/graphql/execution/execute.rb +0 -333
- data/lib/graphql/execution/flatten.rb +0 -40
- data/lib/graphql/execution/lazy/resolve.rb +0 -91
- data/lib/graphql/execution/typecast.rb +0 -50
- data/lib/graphql/field/resolve.rb +0 -59
- data/lib/graphql/field.rb +0 -226
- data/lib/graphql/filter.rb +0 -53
- data/lib/graphql/float_type.rb +0 -2
- data/lib/graphql/function.rb +0 -128
- data/lib/graphql/id_type.rb +0 -2
- data/lib/graphql/input_object_type.rb +0 -138
- data/lib/graphql/int_type.rb +0 -2
- data/lib/graphql/interface_type.rb +0 -72
- data/lib/graphql/internal_representation/document.rb +0 -27
- data/lib/graphql/internal_representation/node.rb +0 -206
- data/lib/graphql/internal_representation/print.rb +0 -51
- data/lib/graphql/internal_representation/rewrite.rb +0 -184
- data/lib/graphql/internal_representation/scope.rb +0 -88
- data/lib/graphql/internal_representation/visit.rb +0 -36
- data/lib/graphql/internal_representation.rb +0 -7
- data/lib/graphql/language/lexer.rl +0 -262
- data/lib/graphql/language/parser.y +0 -543
- data/lib/graphql/list_type.rb +0 -80
- data/lib/graphql/non_null_type.rb +0 -71
- data/lib/graphql/object_type.rb +0 -130
- data/lib/graphql/query/arguments.rb +0 -189
- data/lib/graphql/query/arguments_cache.rb +0 -24
- data/lib/graphql/query/executor.rb +0 -52
- data/lib/graphql/query/literal_input.rb +0 -136
- data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
- data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
- data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
- data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
- data/lib/graphql/query/serial_execution.rb +0 -40
- data/lib/graphql/relay/array_connection.rb +0 -83
- data/lib/graphql/relay/base_connection.rb +0 -189
- data/lib/graphql/relay/connection_instrumentation.rb +0 -54
- data/lib/graphql/relay/connection_resolve.rb +0 -43
- data/lib/graphql/relay/connection_type.rb +0 -41
- data/lib/graphql/relay/edge.rb +0 -27
- data/lib/graphql/relay/edge_type.rb +0 -19
- data/lib/graphql/relay/edges_instrumentation.rb +0 -40
- data/lib/graphql/relay/global_id_resolve.rb +0 -18
- data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
- data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
- data/lib/graphql/relay/mutation/resolve.rb +0 -56
- data/lib/graphql/relay/mutation/result.rb +0 -38
- data/lib/graphql/relay/mutation.rb +0 -106
- data/lib/graphql/relay/node.rb +0 -39
- data/lib/graphql/relay/page_info.rb +0 -7
- data/lib/graphql/relay/relation_connection.rb +0 -188
- data/lib/graphql/relay/type_extensions.rb +0 -32
- data/lib/graphql/scalar_type.rb +0 -91
- data/lib/graphql/schema/base_64_bp.rb +0 -26
- data/lib/graphql/schema/catchall_middleware.rb +0 -35
- data/lib/graphql/schema/default_parse_error.rb +0 -10
- data/lib/graphql/schema/default_type_error.rb +0 -17
- data/lib/graphql/schema/member/accepts_definition.rb +0 -152
- data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -31
- data/lib/graphql/schema/member/instrumentation.rb +0 -131
- data/lib/graphql/schema/middleware_chain.rb +0 -82
- data/lib/graphql/schema/possible_types.rb +0 -44
- data/lib/graphql/schema/rescue_middleware.rb +0 -60
- data/lib/graphql/schema/timeout_middleware.rb +0 -88
- data/lib/graphql/schema/traversal.rb +0 -228
- data/lib/graphql/schema/validation.rb +0 -313
- data/lib/graphql/static_validation/default_visitor.rb +0 -15
- data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
- data/lib/graphql/static_validation/type_stack.rb +0 -216
- data/lib/graphql/string_type.rb +0 -2
- data/lib/graphql/subscriptions/instrumentation.rb +0 -79
- data/lib/graphql/subscriptions/subscription_root.rb +0 -76
- data/lib/graphql/tracing/skylight_tracing.rb +0 -70
- data/lib/graphql/types/relay/default_relay.rb +0 -27
- data/lib/graphql/types/relay/node_field.rb +0 -25
- data/lib/graphql/types/relay/nodes_field.rb +0 -27
- data/lib/graphql/union_type.rb +0 -115
- data/lib/graphql/upgrader/member.rb +0 -937
- data/lib/graphql/upgrader/schema.rb +0 -38
data/lib/graphql/dataloader.rb
CHANGED
@@ -23,23 +23,69 @@ module GraphQL
|
|
23
23
|
# end
|
24
24
|
#
|
25
25
|
class Dataloader
|
26
|
-
|
27
|
-
|
26
|
+
class << self
|
27
|
+
attr_accessor :default_nonblocking
|
28
28
|
end
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
30
|
+
NonblockingDataloader = Class.new(self) { self.default_nonblocking = true }
|
31
|
+
|
32
|
+
def self.use(schema, nonblocking: nil)
|
33
|
+
schema.dataloader_class = if nonblocking
|
34
|
+
warn("`nonblocking: true` is deprecated from `GraphQL::Dataloader`, please use `GraphQL::Dataloader::AsyncDataloader` instead. Docs: https://graphql-ruby.org/dataloader/async_dataloader.")
|
35
|
+
NonblockingDataloader
|
36
|
+
else
|
37
|
+
self
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Call the block with a Dataloader instance,
|
42
|
+
# then run all enqueued jobs and return the result of the block.
|
43
|
+
def self.with_dataloading(&block)
|
44
|
+
dataloader = self.new
|
45
|
+
result = nil
|
46
|
+
dataloader.append_job {
|
47
|
+
result = block.call(dataloader)
|
41
48
|
}
|
49
|
+
dataloader.run
|
50
|
+
result
|
51
|
+
end
|
52
|
+
|
53
|
+
def initialize(nonblocking: self.class.default_nonblocking)
|
54
|
+
@source_cache = Hash.new { |h, k| h[k] = {} }
|
42
55
|
@pending_jobs = []
|
56
|
+
if !nonblocking.nil?
|
57
|
+
@nonblocking = nonblocking
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def nonblocking?
|
62
|
+
@nonblocking
|
63
|
+
end
|
64
|
+
|
65
|
+
# This is called before the fiber is spawned, from the parent context (i.e. from
|
66
|
+
# the thread or fiber that it is scheduled from).
|
67
|
+
#
|
68
|
+
# @return [Hash<Symbol, Object>] Current fiber-local variables
|
69
|
+
def get_fiber_variables
|
70
|
+
fiber_vars = {}
|
71
|
+
Thread.current.keys.each do |fiber_var_key|
|
72
|
+
# This variable should be fresh in each new fiber
|
73
|
+
if fiber_var_key != :__graphql_runtime_info
|
74
|
+
fiber_vars[fiber_var_key] = Thread.current[fiber_var_key]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
fiber_vars
|
78
|
+
end
|
79
|
+
|
80
|
+
# Set up the fiber variables in a new fiber.
|
81
|
+
#
|
82
|
+
# This is called within the fiber, right after it is spawned.
|
83
|
+
#
|
84
|
+
# @param vars [Hash<Symbol, Object>] Fiber-local variables from {get_fiber_variables}
|
85
|
+
# @return [void]
|
86
|
+
def set_fiber_variables(vars)
|
87
|
+
vars.each { |k, v| Thread.current[k] = v }
|
88
|
+
nil
|
43
89
|
end
|
44
90
|
|
45
91
|
# Get a Source instance from this dataloader, for calling `.load(...)` or `.request(...)` on.
|
@@ -48,17 +94,25 @@ module GraphQL
|
|
48
94
|
# @param batch_parameters [Array<Object>]
|
49
95
|
# @return [GraphQL::Dataloader::Source] An instance of {source_class}, initialized with `self, *batch_parameters`,
|
50
96
|
# and cached for the lifetime of this {Multiplex}.
|
51
|
-
if RUBY_VERSION < "3"
|
52
|
-
def with(source_class, *
|
53
|
-
|
97
|
+
if RUBY_VERSION < "3" || RUBY_ENGINE != "ruby" # truffle-ruby wasn't doing well with the implementation below
|
98
|
+
def with(source_class, *batch_args)
|
99
|
+
batch_key = source_class.batch_key_for(*batch_args)
|
100
|
+
@source_cache[source_class][batch_key] ||= begin
|
101
|
+
source = source_class.new(*batch_args)
|
102
|
+
source.setup(self)
|
103
|
+
source
|
104
|
+
end
|
54
105
|
end
|
55
106
|
else
|
56
107
|
def with(source_class, *batch_args, **batch_kwargs)
|
57
|
-
|
58
|
-
@source_cache[source_class][
|
108
|
+
batch_key = source_class.batch_key_for(*batch_args, **batch_kwargs)
|
109
|
+
@source_cache[source_class][batch_key] ||= begin
|
110
|
+
source = source_class.new(*batch_args, **batch_kwargs)
|
111
|
+
source.setup(self)
|
112
|
+
source
|
113
|
+
end
|
59
114
|
end
|
60
115
|
end
|
61
|
-
|
62
116
|
# Tell the dataloader that this fiber is waiting for data.
|
63
117
|
#
|
64
118
|
# Dataloader will resume the fiber after the requested data has been loaded (by another Fiber).
|
@@ -77,9 +131,28 @@ module GraphQL
|
|
77
131
|
nil
|
78
132
|
end
|
79
133
|
|
134
|
+
# Clear any already-loaded objects from {Source} caches
|
135
|
+
# @return [void]
|
136
|
+
def clear_cache
|
137
|
+
@source_cache.each do |_source_class, batched_sources|
|
138
|
+
batched_sources.each_value(&:clear_cache)
|
139
|
+
end
|
140
|
+
nil
|
141
|
+
end
|
142
|
+
|
80
143
|
# Use a self-contained queue for the work in the block.
|
81
144
|
def run_isolated
|
82
145
|
prev_queue = @pending_jobs
|
146
|
+
prev_pending_keys = {}
|
147
|
+
@source_cache.each do |source_class, batched_sources|
|
148
|
+
batched_sources.each do |batch_args, batched_source_instance|
|
149
|
+
if batched_source_instance.pending?
|
150
|
+
prev_pending_keys[batched_source_instance] = batched_source_instance.pending.dup
|
151
|
+
batched_source_instance.pending.clear
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
83
156
|
@pending_jobs = []
|
84
157
|
res = nil
|
85
158
|
# Make sure the block is inside a Fiber, so it can `Fiber.yield`
|
@@ -90,113 +163,99 @@ module GraphQL
|
|
90
163
|
res
|
91
164
|
ensure
|
92
165
|
@pending_jobs = prev_queue
|
166
|
+
prev_pending_keys.each do |source_instance, pending|
|
167
|
+
pending.each do |key, value|
|
168
|
+
if !source_instance.results.key?(key)
|
169
|
+
source_instance.pending[key] = value
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
93
173
|
end
|
94
174
|
|
95
|
-
# @api private Move along, move along
|
96
175
|
def run
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
# - In that case, if there are still pending jobs, a new Fiber will be created to run jobs
|
102
|
-
# - Continue until all jobs have been _started_ by a Fiber. (Any number of those Fibers may be waiting to be resumed, after their data is loaded)
|
103
|
-
# B) Once all known jobs have been run until they are complete or paused for data, run all pending data sources.
|
104
|
-
# - Similarly, create a Fiber to consume pending sources and tell them to load their data.
|
105
|
-
# - If one of those Fibers pauses, then create a new Fiber to continue working through remaining pending sources.
|
106
|
-
# - When a source causes another source to become pending, run the newly-pending source _first_, since it's a dependency of the previous one.
|
107
|
-
# C) After all pending sources have been completely loaded (there are no more pending sources), resume any Fibers that were waiting for data.
|
108
|
-
# - Those Fibers assume that source caches will have been populated with the data they were waiting for.
|
109
|
-
# - Those Fibers may request data from a source again, in which case they will yeilded and be added to a new pending fiber list.
|
110
|
-
# D) Once all pending fibers have been resumed once, return to `A` above.
|
111
|
-
#
|
112
|
-
# For whatever reason, the best implementation I could find was to order the steps `[D, A, B, C]`, with a special case for skipping `D`
|
113
|
-
# on the first pass. I just couldn't find a better way to write the loops in a way that was DRY and easy to read.
|
114
|
-
#
|
115
|
-
pending_fibers = []
|
116
|
-
next_fibers = []
|
176
|
+
job_fibers = []
|
177
|
+
next_job_fibers = []
|
178
|
+
source_fibers = []
|
179
|
+
next_source_fibers = []
|
117
180
|
first_pass = true
|
118
|
-
|
119
|
-
|
120
|
-
if first_pass
|
181
|
+
manager = spawn_fiber do
|
182
|
+
while first_pass || job_fibers.any?
|
121
183
|
first_pass = false
|
122
|
-
else
|
123
|
-
# These fibers were previously waiting for sources to load data,
|
124
|
-
# resume them. (They might wait again, in which case, re-enqueue them.)
|
125
|
-
resume(f)
|
126
|
-
if f.alive?
|
127
|
-
next_fibers << f
|
128
|
-
end
|
129
|
-
end
|
130
184
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
185
|
+
while (f = (job_fibers.shift || spawn_job_fiber))
|
186
|
+
if f.alive?
|
187
|
+
finished = run_fiber(f)
|
188
|
+
if !finished
|
189
|
+
next_job_fibers << f
|
190
|
+
end
|
137
191
|
end
|
138
|
-
}
|
139
|
-
resume(f)
|
140
|
-
# In this case, the job yielded. Queue it up to run again after
|
141
|
-
# we load whatever it's waiting for.
|
142
|
-
if f.alive?
|
143
|
-
next_fibers << f
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
if pending_fibers.empty?
|
148
|
-
# Now, run all Sources which have become pending _before_ resuming GraphQL execution.
|
149
|
-
# Sources might queue up other Sources, which is fine -- those will also run before resuming execution.
|
150
|
-
#
|
151
|
-
# This is where an evented approach would be even better -- can we tell which
|
152
|
-
# fibers are ready to continue, and continue execution there?
|
153
|
-
#
|
154
|
-
source_fiber_queue = if (first_source_fiber = create_source_fiber)
|
155
|
-
[first_source_fiber]
|
156
|
-
else
|
157
|
-
nil
|
158
192
|
end
|
193
|
+
join_queues(job_fibers, next_job_fibers)
|
159
194
|
|
160
|
-
|
161
|
-
while (
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
source_fiber_queue << next_source_fiber
|
168
|
-
end
|
169
|
-
|
170
|
-
if outer_source_fiber.alive?
|
171
|
-
source_fiber_queue << outer_source_fiber
|
195
|
+
while source_fibers.any? || @source_cache.each_value.any? { |group_sources| group_sources.each_value.any?(&:pending?) }
|
196
|
+
while (f = source_fibers.shift || spawn_source_fiber)
|
197
|
+
if f.alive?
|
198
|
+
finished = run_fiber(f)
|
199
|
+
if !finished
|
200
|
+
next_source_fibers << f
|
201
|
+
end
|
172
202
|
end
|
173
203
|
end
|
204
|
+
join_queues(source_fibers, next_source_fibers)
|
174
205
|
end
|
175
|
-
# Move newly-enqueued Fibers on to the list to be resumed.
|
176
|
-
# Clear out the list of next-round Fibers, so that
|
177
|
-
# any Fibers that pause can be put on it.
|
178
|
-
pending_fibers.concat(next_fibers)
|
179
|
-
next_fibers.clear
|
180
206
|
end
|
181
207
|
end
|
182
208
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
raise "Invariant:
|
187
|
-
elsif next_fibers.any?
|
188
|
-
raise "Invariant: #{next_fibers.size} next fibers"
|
209
|
+
run_fiber(manager)
|
210
|
+
|
211
|
+
if manager.alive?
|
212
|
+
raise "Invariant: Manager fiber didn't terminate properly."
|
189
213
|
end
|
190
|
-
|
214
|
+
|
215
|
+
if job_fibers.any?
|
216
|
+
raise "Invariant: job fibers should have exited but #{job_fibers.size} remained"
|
217
|
+
end
|
218
|
+
if source_fibers.any?
|
219
|
+
raise "Invariant: source fibers should have exited but #{source_fibers.size} remained"
|
220
|
+
end
|
221
|
+
rescue UncaughtThrowError => e
|
222
|
+
throw e.tag, e.value
|
223
|
+
end
|
224
|
+
|
225
|
+
def run_fiber(f)
|
226
|
+
f.resume
|
227
|
+
end
|
228
|
+
|
229
|
+
def spawn_fiber
|
230
|
+
fiber_vars = get_fiber_variables
|
231
|
+
Fiber.new(blocking: !@nonblocking) {
|
232
|
+
set_fiber_variables(fiber_vars)
|
233
|
+
yield
|
234
|
+
# With `.transfer`, you have to explicitly pass back to the parent --
|
235
|
+
# if the fiber is allowed to terminate normally, control is passed to the main fiber instead.
|
236
|
+
true
|
237
|
+
}
|
191
238
|
end
|
192
239
|
|
193
240
|
private
|
194
241
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
242
|
+
def join_queues(prev_queue, new_queue)
|
243
|
+
@nonblocking && Fiber.scheduler.run
|
244
|
+
prev_queue.concat(new_queue)
|
245
|
+
new_queue.clear
|
246
|
+
end
|
247
|
+
|
248
|
+
def spawn_job_fiber
|
249
|
+
if @pending_jobs.any?
|
250
|
+
spawn_fiber do
|
251
|
+
while job = @pending_jobs.shift
|
252
|
+
job.call
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
def spawn_source_fiber
|
200
259
|
pending_sources = nil
|
201
260
|
@source_cache.each_value do |source_by_batch_params|
|
202
261
|
source_by_batch_params.each_value do |source|
|
@@ -208,45 +267,12 @@ module GraphQL
|
|
208
267
|
end
|
209
268
|
|
210
269
|
if pending_sources
|
211
|
-
|
212
|
-
# For example, if you have sources `[a, b, c]`, and `a` is loaded, then `b` yields to wait for `d`, then
|
213
|
-
# the next fiber would be dispatched with `[c, d]`. It would fulfill `c`, then `d`, then eventually
|
214
|
-
# the previous fiber would start up again. `c` would no longer be pending, but it would still receive `.run_pending_keys`.
|
215
|
-
# That method is short-circuited since it isn't pending any more, but it's still a waste.
|
216
|
-
#
|
217
|
-
# This design could probably be improved by maintaining a `@pending_sources` queue which is shared by the fibers,
|
218
|
-
# similar to `@pending_jobs`. That way, when a fiber is resumed, it would never pick up work that was finished by a different fiber.
|
219
|
-
source_fiber = spawn_fiber do
|
270
|
+
spawn_fiber do
|
220
271
|
pending_sources.each(&:run_pending_keys)
|
221
272
|
end
|
222
273
|
end
|
223
|
-
|
224
|
-
source_fiber
|
225
|
-
end
|
226
|
-
|
227
|
-
def resume(fiber)
|
228
|
-
fiber.resume
|
229
|
-
rescue UncaughtThrowError => e
|
230
|
-
throw e.tag, e.value
|
231
|
-
end
|
232
|
-
|
233
|
-
# Copies the thread local vars into the fiber thread local vars. Many
|
234
|
-
# gems (such as RequestStore, MiniRacer, etc.) rely on thread local vars
|
235
|
-
# to keep track of execution context, and without this they do not
|
236
|
-
# behave as expected.
|
237
|
-
#
|
238
|
-
# @see https://github.com/rmosolgo/graphql-ruby/issues/3449
|
239
|
-
def spawn_fiber
|
240
|
-
fiber_locals = {}
|
241
|
-
|
242
|
-
Thread.current.keys.each do |fiber_var_key|
|
243
|
-
fiber_locals[fiber_var_key] = Thread.current[fiber_var_key]
|
244
|
-
end
|
245
|
-
|
246
|
-
Fiber.new do
|
247
|
-
fiber_locals.each { |k, v| Thread.current[k] = v }
|
248
|
-
yield
|
249
|
-
end
|
250
274
|
end
|
251
275
|
end
|
252
276
|
end
|
277
|
+
|
278
|
+
require "graphql/dataloader/async_dataloader"
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
# This error is raised when `Types::ISO8601Date` is asked to return a value
|
4
|
+
# that cannot be parsed to a Ruby Date.
|
5
|
+
#
|
6
|
+
# @see GraphQL::Types::ISO8601Date which raises this error
|
7
|
+
class DateEncodingError < GraphQL::RuntimeTypeError
|
8
|
+
# The value which couldn't be encoded
|
9
|
+
attr_reader :date_value
|
10
|
+
|
11
|
+
def initialize(value)
|
12
|
+
@date_value = value
|
13
|
+
super("Date cannot be parsed: #{value}. \nDate must be be able to be parsed as a Ruby Date object.")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/graphql/dig.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
module GraphQL
|
3
3
|
module Dig
|
4
4
|
# implemented using the old activesupport #dig instead of the ruby built-in
|
5
|
-
# so we can use some of the magic in Schema::InputObject and
|
5
|
+
# so we can use some of the magic in Schema::InputObject and Interpreter::Arguments
|
6
6
|
# to handle stringified/symbolized keys.
|
7
7
|
#
|
8
8
|
# @param args [Array<[String, Symbol>] Retrieves the value object corresponding to the each key objects repeatedly
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
# This error is raised when `Types::ISO8601Duration` is asked to return a value
|
4
|
+
# that cannot be parsed as an ISO8601-formatted duration by ActiveSupport::Duration.
|
5
|
+
#
|
6
|
+
# @see GraphQL::Types::ISO8601Duration which raises this error
|
7
|
+
class DurationEncodingError < GraphQL::RuntimeTypeError
|
8
|
+
# The value which couldn't be encoded
|
9
|
+
attr_reader :duration_value
|
10
|
+
|
11
|
+
def initialize(value)
|
12
|
+
@duration_value = value
|
13
|
+
super("Duration cannot be parsed: #{value}. \nDuration must be an ISO8601-formatted duration.")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -2,59 +2,15 @@
|
|
2
2
|
|
3
3
|
module GraphQL
|
4
4
|
module Execution
|
5
|
-
# A plugin that wraps query execution with error handling.
|
6
|
-
# Supports class-based schemas and the new {Interpreter} runtime only.
|
7
|
-
#
|
8
|
-
# @example Handling ActiveRecord::NotFound
|
9
|
-
#
|
10
|
-
# class MySchema < GraphQL::Schema
|
11
|
-
# use GraphQL::Execution::Errors
|
12
|
-
#
|
13
|
-
# rescue_from(ActiveRecord::NotFound) do |err, obj, args, ctx, field|
|
14
|
-
# ErrorTracker.log("Not Found: #{err.message}")
|
15
|
-
# nil
|
16
|
-
# end
|
17
|
-
# end
|
18
|
-
#
|
19
5
|
class Errors
|
20
|
-
def self.use(schema)
|
21
|
-
definition_line = caller(2, 1).first
|
22
|
-
GraphQL::Deprecation.warn("GraphQL::Execution::Errors is now installed by default, remove `use GraphQL::Execution::Errors` from #{definition_line}")
|
23
|
-
end
|
24
|
-
|
25
|
-
NEW_HANDLER_HASH = ->(h, k) {
|
26
|
-
h[k] = {
|
27
|
-
class: k,
|
28
|
-
handler: nil,
|
29
|
-
subclass_handlers: Hash.new(&NEW_HANDLER_HASH),
|
30
|
-
}
|
31
|
-
}
|
32
|
-
|
33
|
-
def initialize(schema)
|
34
|
-
@schema = schema
|
35
|
-
@handlers = {
|
36
|
-
class: nil,
|
37
|
-
handler: nil,
|
38
|
-
subclass_handlers: Hash.new(&NEW_HANDLER_HASH),
|
39
|
-
}
|
40
|
-
end
|
41
|
-
|
42
|
-
# @api private
|
43
|
-
def each_rescue
|
44
|
-
handlers = @handlers.values
|
45
|
-
while (handler = handlers.shift) do
|
46
|
-
yield(handler[:class], handler[:handler])
|
47
|
-
handlers.concat(handler[:subclass_handlers].values)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
6
|
# Register this handler, updating the
|
52
7
|
# internal handler index to maintain least-to-most specific.
|
53
8
|
#
|
54
9
|
# @param error_class [Class<Exception>]
|
10
|
+
# @param error_handlers [Hash]
|
55
11
|
# @param error_handler [Proc]
|
56
12
|
# @return [void]
|
57
|
-
def
|
13
|
+
def self.register_rescue_from(error_class, error_handlers, error_handler)
|
58
14
|
subclasses_handlers = {}
|
59
15
|
this_level_subclasses = []
|
60
16
|
# During this traversal, do two things:
|
@@ -62,13 +18,12 @@ module GraphQL
|
|
62
18
|
# and gather them up to be inserted _under_ this class
|
63
19
|
# - Find the point in the index where this handler should be inserted
|
64
20
|
# (That is, _under_ any superclasses, or at top-level, if there are no superclasses registered)
|
65
|
-
|
66
|
-
while (handlers) do
|
21
|
+
while (error_handlers) do
|
67
22
|
this_level_subclasses.clear
|
68
23
|
# First, identify already-loaded handlers that belong
|
69
24
|
# _under_ this one. (That is, they're handlers
|
70
25
|
# for subclasses of `error_class`.)
|
71
|
-
|
26
|
+
error_handlers.each do |err_class, handler|
|
72
27
|
if err_class < error_class
|
73
28
|
subclasses_handlers[err_class] = handler
|
74
29
|
this_level_subclasses << err_class
|
@@ -76,13 +31,13 @@ module GraphQL
|
|
76
31
|
end
|
77
32
|
# Any handlers that we'll be moving, delete them from this point in the index
|
78
33
|
this_level_subclasses.each do |err_class|
|
79
|
-
|
34
|
+
error_handlers.delete(err_class)
|
80
35
|
end
|
81
36
|
|
82
37
|
# See if any keys in this hash are superclasses of this new class:
|
83
|
-
next_index_point =
|
38
|
+
next_index_point = error_handlers.find { |err_class, handler| error_class < err_class }
|
84
39
|
if next_index_point
|
85
|
-
|
40
|
+
error_handlers = next_index_point[1][:subclass_handlers]
|
86
41
|
else
|
87
42
|
# this new handler doesn't belong to any sub-handlers,
|
88
43
|
# so insert it in the current set of `handlers`
|
@@ -91,39 +46,15 @@ module GraphQL
|
|
91
46
|
end
|
92
47
|
# Having found the point at which to insert this handler,
|
93
48
|
# register it and merge any subclass handlers back in at this point.
|
94
|
-
this_class_handlers =
|
49
|
+
this_class_handlers = error_handlers[error_class]
|
95
50
|
this_class_handlers[:handler] = error_handler
|
96
51
|
this_class_handlers[:subclass_handlers].merge!(subclasses_handlers)
|
97
52
|
nil
|
98
53
|
end
|
99
54
|
|
100
|
-
# Call the given block with the schema's configured error handlers.
|
101
|
-
#
|
102
|
-
# If the block returns a lazy value, it's not wrapped with error handling. That area will have to be wrapped itself.
|
103
|
-
#
|
104
|
-
# @param ctx [GraphQL::Query::Context]
|
105
|
-
# @return [Object] Either the result of the given block, or some object to replace the result, in case of error handling.
|
106
|
-
def with_error_handling(ctx)
|
107
|
-
yield
|
108
|
-
rescue StandardError => err
|
109
|
-
handler = find_handler_for(err.class)
|
110
|
-
if handler
|
111
|
-
runtime_info = ctx.namespace(:interpreter) || {}
|
112
|
-
obj = runtime_info[:current_object]
|
113
|
-
args = runtime_info[:current_arguments]
|
114
|
-
field = runtime_info[:current_field]
|
115
|
-
if obj.is_a?(GraphQL::Schema::Object)
|
116
|
-
obj = obj.object
|
117
|
-
end
|
118
|
-
handler[:handler].call(err, obj, args, ctx, field)
|
119
|
-
else
|
120
|
-
raise err
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
55
|
# @return [Proc, nil] The handler for `error_class`, if one was registered on this schema or inherited
|
125
|
-
def find_handler_for(error_class)
|
126
|
-
handlers =
|
56
|
+
def self.find_handler_for(schema, error_class)
|
57
|
+
handlers = schema.error_handlers[:subclass_handlers]
|
127
58
|
handler = nil
|
128
59
|
while (handlers) do
|
129
60
|
_err_class, next_handler = handlers.find { |err_class, handler| error_class <= err_class }
|
@@ -138,8 +69,8 @@ module GraphQL
|
|
138
69
|
end
|
139
70
|
|
140
71
|
# check for a handler from a parent class:
|
141
|
-
if
|
142
|
-
parent_handler =
|
72
|
+
if schema.superclass.respond_to?(:error_handlers)
|
73
|
+
parent_handler = find_handler_for(schema.superclass, error_class)
|
143
74
|
end
|
144
75
|
|
145
76
|
# If the inherited handler is more specific than the one defined here,
|
@@ -59,7 +59,7 @@ module GraphQL
|
|
59
59
|
@empty
|
60
60
|
end
|
61
61
|
|
62
|
-
def_delegators :keyword_arguments, :key?, :[], :fetch, :keys, :each, :values
|
62
|
+
def_delegators :keyword_arguments, :key?, :[], :fetch, :keys, :each, :values, :size, :to_h
|
63
63
|
def_delegators :argument_values, :each_value
|
64
64
|
|
65
65
|
def inspect
|
@@ -80,7 +80,7 @@ module GraphQL
|
|
80
80
|
)
|
81
81
|
end
|
82
82
|
|
83
|
-
NO_ARGS =
|
83
|
+
NO_ARGS = GraphQL::EmptyObjects::EMPTY_HASH
|
84
84
|
EMPTY = self.new(argument_values: nil, keyword_arguments: NO_ARGS).freeze
|
85
85
|
end
|
86
86
|
end
|