graphql 2.6.11 → 2.6.13
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.
- checksums.yaml +4 -4
- data/.rdoc_options +4 -0
- data/lib/generators/graphql/core.rb +1 -0
- data/lib/generators/graphql/detailed_trace_generator.rb +1 -0
- data/lib/generators/graphql/enum_generator.rb +1 -0
- data/lib/generators/graphql/field_extractor.rb +1 -0
- data/lib/generators/graphql/input_generator.rb +1 -0
- data/lib/generators/graphql/install/mutation_root_generator.rb +1 -0
- data/lib/generators/graphql/install_generator.rb +1 -0
- data/lib/generators/graphql/interface_generator.rb +1 -0
- data/lib/generators/graphql/loader_generator.rb +8 -2
- data/lib/generators/graphql/mutation_create_generator.rb +8 -2
- data/lib/generators/graphql/mutation_delete_generator.rb +8 -2
- data/lib/generators/graphql/mutation_generator.rb +8 -2
- data/lib/generators/graphql/mutation_update_generator.rb +8 -2
- data/lib/generators/graphql/object_generator.rb +1 -0
- data/lib/generators/graphql/orm_mutations_base.rb +8 -2
- data/lib/generators/graphql/relay.rb +1 -0
- data/lib/generators/graphql/relay_generator.rb +1 -0
- data/lib/generators/graphql/scalar_generator.rb +1 -0
- data/lib/generators/graphql/type_generator.rb +38 -8
- data/lib/generators/graphql/union_generator.rb +1 -0
- data/lib/graphql/analysis/analyzer.rb +35 -9
- data/lib/graphql/analysis/field_usage.rb +1 -0
- data/lib/graphql/analysis/max_query_complexity.rb +2 -1
- data/lib/graphql/analysis/max_query_depth.rb +1 -0
- data/lib/graphql/analysis/query_complexity.rb +57 -20
- data/lib/graphql/analysis/query_depth.rb +17 -12
- data/lib/graphql/analysis/visitor.rb +79 -16
- data/lib/graphql/analysis.rb +23 -6
- data/lib/graphql/analysis_error.rb +1 -0
- data/lib/graphql/autoload.rb +30 -7
- data/lib/graphql/backtrace/table.rb +21 -5
- data/lib/graphql/backtrace/traced_error.rb +8 -3
- data/lib/graphql/backtrace.rb +14 -9
- data/lib/graphql/coercion_error.rb +1 -0
- data/lib/graphql/current.rb +44 -19
- data/lib/graphql/dashboard/application_controller.rb +1 -0
- data/lib/graphql/dashboard/detailed_traces.rb +1 -0
- data/lib/graphql/dashboard/installable.rb +1 -0
- data/lib/graphql/dashboard/landings_controller.rb +1 -0
- data/lib/graphql/dashboard/limiters.rb +1 -0
- data/lib/graphql/dashboard/operation_store.rb +1 -0
- data/lib/graphql/dashboard/statics_controller.rb +1 -0
- data/lib/graphql/dashboard/subscriptions.rb +1 -0
- data/lib/graphql/dashboard.rb +36 -22
- data/lib/graphql/dataloader/active_record_association_source.rb +1 -0
- data/lib/graphql/dataloader/active_record_source.rb +1 -0
- data/lib/graphql/dataloader/async_dataloader.rb +10 -7
- data/lib/graphql/dataloader/null_dataloader.rb +4 -3
- data/lib/graphql/dataloader/request.rb +8 -2
- data/lib/graphql/dataloader/request_all.rb +8 -2
- data/lib/graphql/dataloader/source.rb +127 -35
- data/lib/graphql/dataloader.rb +93 -42
- data/lib/graphql/date_encoding_error.rb +2 -1
- data/lib/graphql/dig.rb +12 -3
- data/lib/graphql/duration_encoding_error.rb +2 -1
- data/lib/graphql/execution/directive_checks.rb +8 -3
- data/lib/graphql/execution/errors.rb +20 -6
- data/lib/graphql/execution/field_resolve_step.rb +40 -13
- data/lib/graphql/execution/finalize.rb +12 -6
- data/lib/graphql/execution/input_values.rb +2 -1
- data/lib/graphql/execution/interpreter/argument_value.rb +17 -5
- data/lib/graphql/execution/interpreter/arguments.rb +24 -9
- data/lib/graphql/execution/interpreter/arguments_cache.rb +2 -1
- data/lib/graphql/execution/interpreter/execution_errors.rb +1 -0
- data/lib/graphql/execution/interpreter/handles_raw_value.rb +1 -0
- data/lib/graphql/execution/interpreter/resolve.rb +18 -8
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +4 -1
- data/lib/graphql/execution/interpreter/runtime.rb +72 -25
- data/lib/graphql/execution/interpreter.rb +15 -6
- data/lib/graphql/execution/lazy/lazy_method_map.rb +21 -8
- data/lib/graphql/execution/lazy.rb +34 -10
- data/lib/graphql/execution/load_argument_step.rb +1 -0
- data/lib/graphql/execution/lookahead.rb +137 -54
- data/lib/graphql/execution/multiplex.rb +4 -4
- data/lib/graphql/execution/next.rb +7 -0
- data/lib/graphql/execution/prepare_object_step.rb +1 -0
- data/lib/graphql/execution/resolve_type_step.rb +2 -1
- data/lib/graphql/execution/runner.rb +9 -3
- data/lib/graphql/execution/selections_step.rb +3 -2
- data/lib/graphql/execution.rb +2 -2
- data/lib/graphql/execution_error.rb +19 -10
- data/lib/graphql/float_decoding_error.rb +1 -0
- data/lib/graphql/float_encoding_error.rb +7 -2
- data/lib/graphql/integer_decoding_error.rb +2 -1
- data/lib/graphql/integer_encoding_error.rb +8 -3
- data/lib/graphql/introspection/base_object.rb +3 -1
- data/lib/graphql/introspection/directive_location_enum.rb +1 -0
- data/lib/graphql/introspection/directive_type.rb +1 -0
- data/lib/graphql/introspection/dynamic_fields.rb +1 -0
- data/lib/graphql/introspection/entry_points.rb +1 -0
- data/lib/graphql/introspection/enum_value_type.rb +1 -0
- data/lib/graphql/introspection/field_type.rb +1 -0
- data/lib/graphql/introspection/input_value_type.rb +1 -0
- data/lib/graphql/introspection/introspection_query.rb +1 -0
- data/lib/graphql/introspection/schema_type.rb +1 -0
- data/lib/graphql/introspection/type_kind_enum.rb +1 -0
- data/lib/graphql/introspection/type_type.rb +1 -0
- data/lib/graphql/introspection.rb +1 -0
- data/lib/graphql/invalid_name_error.rb +1 -0
- data/lib/graphql/invalid_null_error.rb +19 -6
- data/lib/graphql/language/block_string.rb +2 -1
- data/lib/graphql/language/cache.rb +10 -4
- data/lib/graphql/language/comment.rb +1 -0
- data/lib/graphql/language/definition_slice.rb +1 -0
- data/lib/graphql/language/document_from_schema_definition.rb +9 -10
- data/lib/graphql/language/generation.rb +23 -9
- data/lib/graphql/language/lexer.rb +5 -0
- data/lib/graphql/language/nodes.rb +2094 -419
- data/lib/graphql/language/parser.rb +24 -17
- data/lib/graphql/language/printer.rb +31 -16
- data/lib/graphql/language/sanitized_printer.rb +16 -5
- data/lib/graphql/language/static_visitor.rb +19 -4
- data/lib/graphql/language/visitor.rb +51 -29
- data/lib/graphql/language.rb +13 -7
- data/lib/graphql/load_application_object_failed_error.rb +14 -5
- data/lib/graphql/name_validator.rb +1 -0
- data/lib/graphql/pagination/active_record_relation_connection.rb +1 -0
- data/lib/graphql/pagination/array_connection.rb +20 -6
- data/lib/graphql/pagination/connection.rb +178 -48
- data/lib/graphql/pagination/connections.rb +21 -14
- data/lib/graphql/pagination/mongoid_relation_connection.rb +1 -0
- data/lib/graphql/pagination/relation_connection.rb +123 -22
- data/lib/graphql/pagination/sequel_dataset_connection.rb +1 -0
- data/lib/graphql/pagination.rb +1 -0
- data/lib/graphql/parse_error.rb +1 -0
- data/lib/graphql/query/context/scoped_context.rb +2 -1
- data/lib/graphql/query/context.rb +106 -35
- data/lib/graphql/query/fingerprint.rb +15 -7
- data/lib/graphql/query/input_validation_result.rb +1 -0
- data/lib/graphql/query/null_context.rb +1 -0
- data/lib/graphql/query/partial.rb +28 -15
- data/lib/graphql/query/result.rb +15 -5
- data/lib/graphql/query/validation_pipeline.rb +16 -6
- data/lib/graphql/query/variable_validation_error.rb +1 -0
- data/lib/graphql/query/variables.rb +9 -2
- data/lib/graphql/query.rb +193 -49
- data/lib/graphql/railtie.rb +7 -3
- data/lib/graphql/rake_task/validate.rb +72 -17
- data/lib/graphql/rake_task.rb +55 -23
- data/lib/graphql/relay/range_add.rb +32 -21
- data/lib/graphql/relay.rb +1 -0
- data/lib/graphql/rubocop/graphql/base_cop.rb +1 -0
- data/lib/graphql/rubocop/graphql/default_null_true.rb +9 -6
- data/lib/graphql/rubocop/graphql/default_required_true.rb +9 -6
- data/lib/graphql/rubocop/graphql/field_type_in_block.rb +12 -8
- data/lib/graphql/rubocop/graphql/root_types_in_block.rb +9 -5
- data/lib/graphql/rubocop.rb +1 -0
- data/lib/graphql/runtime_error.rb +1 -0
- data/lib/graphql/runtime_type_error.rb +1 -0
- data/lib/graphql/schema/addition.rb +18 -6
- data/lib/graphql/schema/always_visible.rb +1 -0
- data/lib/graphql/schema/argument.rb +265 -42
- data/lib/graphql/schema/base_64_encoder.rb +2 -2
- data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +1 -0
- data/lib/graphql/schema/build_from_definition/resolve_map.rb +2 -2
- data/lib/graphql/schema/build_from_definition.rb +94 -27
- data/lib/graphql/schema/built_in_types.rb +1 -0
- data/lib/graphql/schema/directive/deprecated.rb +1 -0
- data/lib/graphql/schema/directive/feature.rb +39 -22
- data/lib/graphql/schema/directive/flagged.rb +6 -1
- data/lib/graphql/schema/directive/include.rb +1 -0
- data/lib/graphql/schema/directive/one_of.rb +1 -0
- data/lib/graphql/schema/directive/skip.rb +1 -0
- data/lib/graphql/schema/directive/specified_by.rb +1 -0
- data/lib/graphql/schema/directive/transform.rb +17 -8
- data/lib/graphql/schema/directive.rb +12 -7
- data/lib/graphql/schema/enum.rb +99 -38
- data/lib/graphql/schema/enum_value.rb +21 -13
- data/lib/graphql/schema/field/connection_extension.rb +10 -2
- data/lib/graphql/schema/field/scope_extension.rb +1 -0
- data/lib/graphql/schema/field.rb +621 -109
- data/lib/graphql/schema/field_extension.rb +89 -34
- data/lib/graphql/schema/find_inherited_value.rb +5 -3
- data/lib/graphql/schema/finder.rb +22 -8
- data/lib/graphql/schema/has_single_input_argument.rb +39 -6
- data/lib/graphql/schema/input_object.rb +40 -13
- data/lib/graphql/schema/interface.rb +33 -17
- data/lib/graphql/schema/introspection_system.rb +7 -3
- data/lib/graphql/schema/late_bound_type.rb +2 -2
- data/lib/graphql/schema/list.rb +15 -4
- data/lib/graphql/schema/loader.rb +23 -12
- data/lib/graphql/schema/member/base_dsl_methods.rb +58 -12
- data/lib/graphql/schema/member/build_type.rb +16 -5
- data/lib/graphql/schema/member/graphql_type_names.rb +10 -6
- data/lib/graphql/schema/member/has_arguments.rb +115 -48
- data/lib/graphql/schema/member/has_ast_node.rb +1 -0
- data/lib/graphql/schema/member/has_authorization.rb +5 -0
- data/lib/graphql/schema/member/has_dataloader.rb +91 -34
- data/lib/graphql/schema/member/has_deprecation_reason.rb +15 -2
- data/lib/graphql/schema/member/has_directives.rb +38 -10
- data/lib/graphql/schema/member/has_fields.rb +151 -70
- data/lib/graphql/schema/member/has_interfaces.rb +10 -2
- data/lib/graphql/schema/member/has_path.rb +14 -5
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +1 -0
- data/lib/graphql/schema/member/has_validators.rb +19 -4
- data/lib/graphql/schema/member/relay_shortcuts.rb +10 -2
- data/lib/graphql/schema/member/scoped.rb +14 -3
- data/lib/graphql/schema/member/type_system_helpers.rb +36 -6
- data/lib/graphql/schema/member/validates_input.rb +1 -0
- data/lib/graphql/schema/member.rb +9 -2
- data/lib/graphql/schema/mutation.rb +50 -46
- data/lib/graphql/schema/non_null.rb +21 -5
- data/lib/graphql/schema/object.rb +33 -12
- data/lib/graphql/schema/printer.rb +52 -31
- data/lib/graphql/schema/ractor_shareable.rb +6 -2
- data/lib/graphql/schema/relay_classic_mutation.rb +3 -3
- data/lib/graphql/schema/resolver/has_payload_type.rb +29 -7
- data/lib/graphql/schema/resolver.rb +156 -45
- data/lib/graphql/schema/scalar.rb +1 -0
- data/lib/graphql/schema/subscription.rb +67 -28
- data/lib/graphql/schema/timeout.rb +65 -25
- data/lib/graphql/schema/type_expression.rb +14 -5
- data/lib/graphql/schema/type_membership.rb +29 -10
- data/lib/graphql/schema/union.rb +4 -2
- data/lib/graphql/schema/unique_within_type.rb +24 -5
- data/lib/graphql/schema/validator/all_validator.rb +17 -9
- data/lib/graphql/schema/validator/allow_blank_validator.rb +8 -2
- data/lib/graphql/schema/validator/allow_null_validator.rb +8 -2
- data/lib/graphql/schema/validator/exclusion_validator.rb +14 -5
- data/lib/graphql/schema/validator/format_validator.rb +21 -10
- data/lib/graphql/schema/validator/inclusion_validator.rb +15 -6
- data/lib/graphql/schema/validator/length_validator.rb +23 -12
- data/lib/graphql/schema/validator/numericality_validator.rb +29 -16
- data/lib/graphql/schema/validator/required_validator.rb +45 -31
- data/lib/graphql/schema/validator.rb +89 -25
- data/lib/graphql/schema/visibility/migration.rb +14 -7
- data/lib/graphql/schema/visibility/profile.rb +65 -20
- data/lib/graphql/schema/visibility/visit.rb +12 -10
- data/lib/graphql/schema/visibility.rb +24 -20
- data/lib/graphql/schema/warden.rb +117 -31
- data/lib/graphql/schema/wrapper.rb +4 -1
- data/lib/graphql/schema.rb +1046 -300
- data/lib/graphql/static_validation/all_rules.rb +2 -1
- data/lib/graphql/static_validation/base_visitor.rb +59 -9
- data/lib/graphql/static_validation/definition_dependencies.rb +27 -7
- data/lib/graphql/static_validation/error.rb +3 -0
- data/lib/graphql/static_validation/interpreter_visitor.rb +1 -0
- data/lib/graphql/static_validation/literal_validator.rb +1 -0
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +4 -0
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +1 -0
- data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +3 -0
- data/lib/graphql/static_validation/rules/argument_names_are_unique_error.rb +1 -0
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +3 -0
- data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +1 -0
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +3 -0
- data/lib/graphql/static_validation/rules/directives_are_defined_error.rb +1 -0
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +3 -0
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations_error.rb +1 -0
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +3 -0
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type_error.rb +1 -0
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +9 -1
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections_error.rb +1 -0
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +295 -134
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +14 -2
- data/lib/graphql/static_validation/rules/fragment_names_are_unique.rb +3 -0
- data/lib/graphql/static_validation/rules/fragment_names_are_unique_error.rb +1 -0
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -0
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible_error.rb +1 -0
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +3 -0
- data/lib/graphql/static_validation/rules/fragment_types_exist_error.rb +1 -0
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +3 -0
- data/lib/graphql/static_validation/rules/fragments_are_finite_error.rb +1 -0
- data/lib/graphql/static_validation/rules/fragments_are_named.rb +3 -0
- data/lib/graphql/static_validation/rules/fragments_are_named_error.rb +1 -0
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +3 -0
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types_error.rb +1 -0
- data/lib/graphql/static_validation/rules/fragments_are_used.rb +3 -0
- data/lib/graphql/static_validation/rules/fragments_are_used_error.rb +1 -0
- data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +3 -0
- data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +1 -0
- data/lib/graphql/static_validation/rules/mutation_root_exists.rb +3 -0
- data/lib/graphql/static_validation/rules/mutation_root_exists_error.rb +1 -0
- data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +3 -0
- data/lib/graphql/static_validation/rules/no_definitions_are_present_error.rb +1 -0
- data/lib/graphql/static_validation/rules/not_single_subscription_error.rb +1 -0
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +4 -0
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +1 -0
- data/lib/graphql/static_validation/rules/operation_names_are_valid.rb +3 -0
- data/lib/graphql/static_validation/rules/operation_names_are_valid_error.rb +1 -0
- data/lib/graphql/static_validation/rules/query_root_exists.rb +3 -0
- data/lib/graphql/static_validation/rules/query_root_exists_error.rb +1 -0
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -1
- data/lib/graphql/static_validation/rules/required_arguments_are_present_error.rb +1 -0
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +4 -0
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present_error.rb +1 -0
- data/lib/graphql/static_validation/rules/subscription_root_exists_and_single_subscription_selection.rb +43 -5
- data/lib/graphql/static_validation/rules/subscription_root_exists_error.rb +1 -0
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +3 -0
- data/lib/graphql/static_validation/rules/unique_directives_per_location_error.rb +1 -0
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +3 -0
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed_error.rb +1 -0
- data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +3 -0
- data/lib/graphql/static_validation/rules/variable_names_are_unique_error.rb +1 -0
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +207 -51
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed_error.rb +1 -0
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +3 -0
- data/lib/graphql/static_validation/rules/variables_are_input_types_error.rb +1 -0
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +6 -3
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined_error.rb +1 -0
- data/lib/graphql/static_validation/validation_context.rb +3 -2
- data/lib/graphql/static_validation/validation_timeout_error.rb +1 -0
- data/lib/graphql/static_validation/validator.rb +41 -16
- data/lib/graphql/static_validation.rb +1 -0
- data/lib/graphql/string_encoding_error.rb +1 -0
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +85 -65
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +10 -4
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +1 -0
- data/lib/graphql/subscriptions/event.rb +25 -6
- data/lib/graphql/subscriptions/serialize.rb +58 -19
- data/lib/graphql/subscriptions.rb +172 -46
- data/lib/graphql/testing/helpers.rb +17 -4
- data/lib/graphql/testing/mock_action_cable.rb +55 -33
- data/lib/graphql/testing.rb +1 -0
- data/lib/graphql/tracing/active_support_notifications_trace.rb +17 -9
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +2 -1
- data/lib/graphql/tracing/appoptics_trace.rb +2 -1
- data/lib/graphql/tracing/appoptics_tracing.rb +2 -1
- data/lib/graphql/tracing/appsignal_trace.rb +16 -7
- data/lib/graphql/tracing/appsignal_tracing.rb +7 -3
- data/lib/graphql/tracing/call_legacy_tracers.rb +1 -0
- data/lib/graphql/tracing/data_dog_trace.rb +17 -6
- data/lib/graphql/tracing/data_dog_tracing.rb +10 -3
- data/lib/graphql/tracing/detailed_trace/active_record_backend.rb +1 -0
- data/lib/graphql/tracing/detailed_trace/memory_backend.rb +1 -0
- data/lib/graphql/tracing/detailed_trace/redis_backend.rb +1 -0
- data/lib/graphql/tracing/detailed_trace.rb +105 -42
- data/lib/graphql/tracing/legacy_hooks_trace.rb +5 -0
- data/lib/graphql/tracing/legacy_trace.rb +1 -0
- data/lib/graphql/tracing/monitor_trace.rb +17 -11
- data/lib/graphql/tracing/new_relic_trace.rb +17 -8
- data/lib/graphql/tracing/new_relic_tracing.rb +7 -3
- data/lib/graphql/tracing/notifications_trace.rb +11 -8
- data/lib/graphql/tracing/notifications_tracing.rb +23 -7
- data/lib/graphql/tracing/null_trace.rb +1 -0
- data/lib/graphql/tracing/perfetto_trace/trace_pb.rb +1 -0
- data/lib/graphql/tracing/perfetto_trace.rb +41 -19
- data/lib/graphql/tracing/platform_trace.rb +3 -1
- data/lib/graphql/tracing/platform_tracing.rb +16 -7
- data/lib/graphql/tracing/prometheus_trace/graphql_collector.rb +1 -0
- data/lib/graphql/tracing/prometheus_trace.rb +22 -13
- data/lib/graphql/tracing/prometheus_tracing.rb +1 -0
- data/lib/graphql/tracing/scout_trace.rb +10 -4
- data/lib/graphql/tracing/scout_tracing.rb +7 -3
- data/lib/graphql/tracing/sentry_trace.rb +12 -5
- data/lib/graphql/tracing/statsd_trace.rb +12 -6
- data/lib/graphql/tracing/statsd_tracing.rb +7 -1
- data/lib/graphql/tracing/trace.rb +231 -58
- data/lib/graphql/tracing.rb +25 -9
- data/lib/graphql/type_kinds.rb +2 -1
- data/lib/graphql/types/big_int.rb +1 -0
- data/lib/graphql/types/boolean.rb +1 -0
- data/lib/graphql/types/float.rb +1 -0
- data/lib/graphql/types/id.rb +1 -0
- data/lib/graphql/types/int.rb +2 -1
- data/lib/graphql/types/iso_8601_date.rb +21 -4
- data/lib/graphql/types/iso_8601_date_time.rb +33 -6
- data/lib/graphql/types/iso_8601_duration.rb +42 -9
- data/lib/graphql/types/json.rb +1 -0
- data/lib/graphql/types/relay/base_connection.rb +38 -32
- data/lib/graphql/types/relay/base_edge.rb +15 -9
- data/lib/graphql/types/relay/connection_behaviors.rb +19 -3
- data/lib/graphql/types/relay/edge_behaviors.rb +17 -4
- data/lib/graphql/types/relay/has_node_field.rb +6 -1
- data/lib/graphql/types/relay/has_nodes_field.rb +6 -1
- data/lib/graphql/types/relay/node.rb +1 -0
- data/lib/graphql/types/relay/node_behaviors.rb +5 -1
- data/lib/graphql/types/relay/page_info.rb +1 -0
- data/lib/graphql/types/relay/page_info_behaviors.rb +1 -0
- data/lib/graphql/types/relay.rb +4 -3
- data/lib/graphql/types/string.rb +1 -0
- data/lib/graphql/types.rb +1 -0
- data/lib/graphql/unauthorized_enum_value_error.rb +4 -1
- data/lib/graphql/unauthorized_error.rb +11 -4
- data/lib/graphql/unauthorized_field_error.rb +4 -1
- data/lib/graphql/unresolved_type_error.rb +16 -5
- data/lib/graphql/version.rb +2 -1
- data/lib/graphql.rb +37 -9
- data/readme.md +1 -1
- metadata +89 -5
- data/.yardopts +0 -5
data/lib/graphql/schema.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
# typed: false
|
|
2
3
|
require "logger"
|
|
3
4
|
require "graphql/schema/addition"
|
|
4
5
|
require "graphql/schema/always_visible"
|
|
@@ -48,28 +49,121 @@ require "graphql/schema/subscription"
|
|
|
48
49
|
require "graphql/schema/visibility"
|
|
49
50
|
|
|
50
51
|
module GraphQL
|
|
51
|
-
# A GraphQL schema which may be queried with
|
|
52
|
+
# A GraphQL schema which may be queried with [GraphQL::Query](rdoc-ref:GraphQL::Query).
|
|
52
53
|
#
|
|
53
|
-
# The
|
|
54
|
+
# The [Schema](rdoc-ref:Schema) contains:
|
|
54
55
|
#
|
|
55
56
|
# - types for exposing your application
|
|
56
57
|
# - query analyzers for assessing incoming queries (including max depth & max complexity restrictions)
|
|
57
58
|
# - execution strategies for running incoming queries
|
|
58
59
|
#
|
|
59
|
-
# Schemas start with root types,
|
|
60
|
+
# Schemas start with root types, [Schema.query](rdoc-ref:GraphQL::Schema::query), [Schema.mutation](rdoc-ref:GraphQL::Schema::mutation) and [Schema.subscription](rdoc-ref:GraphQL::Schema::subscription).
|
|
60
61
|
# The schema will traverse the tree of fields & types, using those as starting points.
|
|
61
62
|
# Any undiscoverable types may be provided with the `types` configuration.
|
|
62
63
|
#
|
|
63
64
|
# Schemas can restrict large incoming queries with `max_depth` and `max_complexity` configurations.
|
|
64
|
-
# (These configurations can be overridden by specific calls to
|
|
65
|
+
# (These configurations can be overridden by specific calls to [Schema.execute](rdoc-ref:Schema.execute))
|
|
65
66
|
#
|
|
66
|
-
#
|
|
67
|
-
# class MySchema < GraphQL::Schema
|
|
68
|
-
# query QueryType
|
|
69
|
-
# # If types are only connected by way of interfaces, they must be added here
|
|
70
|
-
# orphan_types ImageType, AudioType
|
|
71
|
-
# end
|
|
67
|
+
# **Schema configuration reference**
|
|
72
68
|
#
|
|
69
|
+
# - Root types are registered with `query`, `mutation`, and `subscription`; use `orphan_types` for interface-only object types.
|
|
70
|
+
# - `object_from_id`, `id_from_object`, and `resolve_type` implement Relay object identification and abstract-type resolution.
|
|
71
|
+
# - `type_error`, `rescue_from`, `parse_error`, and `query_stack_error` provide execution error hooks.
|
|
72
|
+
# - `max_depth`, `max_complexity`, `validate_timeout`, `validate_max_errors`, and `max_query_string_tokens` limit incoming work.
|
|
73
|
+
# - `extra_types`, `introspection`, `trace_with`, analyzers, `context_class`, `query_class`, `lazy_resolve`, and `use` configure execution.
|
|
74
|
+
#
|
|
75
|
+
# The [schema definition guide](/schema/definition) contains setup examples and
|
|
76
|
+
# links each contract above to its API method. Keep method-specific behavior in
|
|
77
|
+
# the comments for those methods so this page remains the source of truth.
|
|
78
|
+
#
|
|
79
|
+
# ## Root Types
|
|
80
|
+
#
|
|
81
|
+
# `query`, `mutation`, and `subscription` register the entry-point object types
|
|
82
|
+
# for a schema. Each may receive a type class or a block for lazy loading:
|
|
83
|
+
#
|
|
84
|
+
# ```ruby
|
|
85
|
+
# query Types::Query
|
|
86
|
+
# mutation { Types::Mutation }
|
|
87
|
+
# subscription { Types::Subscription }
|
|
88
|
+
# ```
|
|
89
|
+
#
|
|
90
|
+
# Use [Schema.orphan_types](rdoc-ref:GraphQL::Schema.orphan_types) for object
|
|
91
|
+
# types which implement an interface but aren't reachable from a field return
|
|
92
|
+
# type. Use [Schema.extra_types](rdoc-ref:GraphQL::Schema.extra_types) when a
|
|
93
|
+
# type should be printed and included in introspection without being connected
|
|
94
|
+
# to the schema's type graph.
|
|
95
|
+
#
|
|
96
|
+
# ## Object Identification
|
|
97
|
+
#
|
|
98
|
+
# Relay-style `node(id:)` fields, arguments configured with `loads:`, and the
|
|
99
|
+
# ObjectCache use [Schema.object_from_id](rdoc-ref:GraphQL::Schema.object_from_id)
|
|
100
|
+
# to fetch an application object. Return `nil` when the object does not exist or
|
|
101
|
+
# is not visible to the current operation. Implement
|
|
102
|
+
# [Schema.id_from_object](rdoc-ref:GraphQL::Schema.id_from_object) to produce a
|
|
103
|
+
# stable ID which can be passed back to `object_from_id`.
|
|
104
|
+
#
|
|
105
|
+
# [Schema.resolve_type](rdoc-ref:GraphQL::Schema.resolve_type) maps an
|
|
106
|
+
# application object to its runtime GraphQL type when a field returns an
|
|
107
|
+
# interface or union.
|
|
108
|
+
#
|
|
109
|
+
# ## Error Handling
|
|
110
|
+
#
|
|
111
|
+
# Override [Schema.type_error](rdoc-ref:GraphQL::Schema.type_error) to handle
|
|
112
|
+
# mismatches between application values and the GraphQL type system. Register
|
|
113
|
+
# application exception handlers with [Schema.rescue_from](rdoc-ref:GraphQL::Schema.rescue_from).
|
|
114
|
+
# [Schema.parse_error](rdoc-ref:GraphQL::Schema.parse_error) handles invalid
|
|
115
|
+
# query strings, and [Schema.query_stack_error](rdoc-ref:GraphQL::Schema.query_stack_error)
|
|
116
|
+
# is called when execution encounters a `SystemStackError`.
|
|
117
|
+
#
|
|
118
|
+
# ## Default Limits
|
|
119
|
+
#
|
|
120
|
+
# [Schema.max_depth](rdoc-ref:GraphQL::Schema.max_depth) limits nested field
|
|
121
|
+
# selections and [Schema.max_complexity](rdoc-ref:GraphQL::Schema.max_complexity)
|
|
122
|
+
# limits the calculated cost of a query. [Schema.default_max_page_size](rdoc-ref:GraphQL::Schema.default_max_page_size)
|
|
123
|
+
# limits connection fields. [Schema.validate_timeout](rdoc-ref:GraphQL::Schema.validate_timeout),
|
|
124
|
+
# [Schema.validate_max_errors](rdoc-ref:GraphQL::Schema.validate_max_errors), and
|
|
125
|
+
# [Schema.max_query_string_tokens](rdoc-ref:GraphQL::Schema.max_query_string_tokens)
|
|
126
|
+
# bound validation and parsing work. These limits can be configured on a schema
|
|
127
|
+
# and, where documented, overridden for an individual execution.
|
|
128
|
+
#
|
|
129
|
+
# ## Introspection
|
|
130
|
+
#
|
|
131
|
+
# [Schema.extra_types](rdoc-ref:GraphQL::Schema.extra_types) adds otherwise
|
|
132
|
+
# unreachable types to printed SDL and introspection results. Pass a custom
|
|
133
|
+
# namespace to [Schema.introspection](rdoc-ref:GraphQL::Schema.introspection) to
|
|
134
|
+
# replace or extend the default introspection system.
|
|
135
|
+
#
|
|
136
|
+
# ## Authorization
|
|
137
|
+
#
|
|
138
|
+
# [Schema.unauthorized_object](rdoc-ref:GraphQL::Schema.unauthorized_object)
|
|
139
|
+
# and [Schema.unauthorized_field](rdoc-ref:GraphQL::Schema.unauthorized_field)
|
|
140
|
+
# run when an authorization hook returns `false`. Return a replacement value or
|
|
141
|
+
# raise [GraphQL::ExecutionError](rdoc-ref:GraphQL::ExecutionError) to add a
|
|
142
|
+
# client-facing error.
|
|
143
|
+
#
|
|
144
|
+
# ## Execution Configuration
|
|
145
|
+
#
|
|
146
|
+
# [Schema.trace_with](rdoc-ref:GraphQL::Schema.trace_with) installs tracing
|
|
147
|
+
# modules. [Schema.query_analyzer](rdoc-ref:GraphQL::Schema.query_analyzer) and
|
|
148
|
+
# [Schema.multiplex_analyzer](rdoc-ref:GraphQL::Schema.multiplex_analyzer)
|
|
149
|
+
# register analysis hooks. [Schema.default_logger](rdoc-ref:GraphQL::Schema.default_logger)
|
|
150
|
+
# configures runtime logging, while [Schema.context_class](rdoc-ref:GraphQL::Schema.context_class)
|
|
151
|
+
# and [Schema.query_class](rdoc-ref:GraphQL::Schema.query_class) select the
|
|
152
|
+
# classes used during execution. [Schema.lazy_resolve](rdoc-ref:GraphQL::Schema.lazy_resolve)
|
|
153
|
+
# registers promise-like values, and [Schema.use](rdoc-ref:GraphQL::Schema.use)
|
|
154
|
+
# installs schema plugins such as Dataloader and Visibility.
|
|
155
|
+
#
|
|
156
|
+
# **Examples**
|
|
157
|
+
#
|
|
158
|
+
# **Example: defining a schema**
|
|
159
|
+
#
|
|
160
|
+
# ```ruby
|
|
161
|
+
# class MySchema < GraphQL::Schema
|
|
162
|
+
# query QueryType
|
|
163
|
+
# # If types are only connected by way of interfaces, they must be added here
|
|
164
|
+
# orphan_types ImageType, AudioType
|
|
165
|
+
# end
|
|
166
|
+
# ```
|
|
73
167
|
class Schema
|
|
74
168
|
extend GraphQL::Schema::Member::HasAstNode
|
|
75
169
|
extend GraphQL::Schema::FindInheritedValue
|
|
@@ -99,19 +193,38 @@ module GraphQL
|
|
|
99
193
|
class InvalidDocumentError < Error; end;
|
|
100
194
|
|
|
101
195
|
class << self
|
|
196
|
+
include EmptyObjects
|
|
102
197
|
# Create schema with the result of an introspection query.
|
|
103
|
-
#
|
|
104
|
-
#
|
|
198
|
+
#
|
|
199
|
+
# **Parameters**
|
|
200
|
+
#
|
|
201
|
+
# - `introspection_result` (`Hash`) — A response from [GraphQL::Introspection::INTROSPECTION_QUERY](rdoc-ref:GraphQL::Introspection::INTROSPECTION_QUERY)
|
|
202
|
+
#
|
|
203
|
+
# **Returns**
|
|
204
|
+
#
|
|
205
|
+
# - `Class<GraphQL::Schema>` — the schema described by `input`
|
|
206
|
+
#
|
|
207
|
+
# :call-seq:
|
|
208
|
+
# from_introspection(Hash introspection_result) -> Class[GraphQL::Schema]
|
|
105
209
|
def from_introspection(introspection_result)
|
|
106
210
|
GraphQL::Schema::Loader.load(introspection_result)
|
|
107
211
|
end
|
|
108
212
|
|
|
109
213
|
# Create schema from an IDL schema or file containing an IDL definition.
|
|
110
|
-
#
|
|
111
|
-
#
|
|
112
|
-
#
|
|
113
|
-
#
|
|
114
|
-
#
|
|
214
|
+
#
|
|
215
|
+
# **Parameters**
|
|
216
|
+
#
|
|
217
|
+
# - `definition_or_path` (`String`) — A schema definition string, or a path to a file containing the definition
|
|
218
|
+
# - `default_resolve` (`<#call(type, field, obj, args, ctx)>`) — A callable for handling field resolution
|
|
219
|
+
# - `parser` (`Object`) — An object for handling definition string parsing (must respond to `parse`)
|
|
220
|
+
# - `using` (`Hash`) — Plugins to attach to the created schema with `use(key, value)`
|
|
221
|
+
#
|
|
222
|
+
# **Returns**
|
|
223
|
+
#
|
|
224
|
+
# - `Class` — the schema described by `document`
|
|
225
|
+
#
|
|
226
|
+
# :call-seq:
|
|
227
|
+
# from_definition(String definition_or_path, #call(type, field, obj, args, ctx) default_resolve:, Object parser:, Hash using:, base_types:) -> Class
|
|
115
228
|
def from_definition(definition_or_path, default_resolve: nil, parser: GraphQL.default_parser, using: {}, base_types: {})
|
|
116
229
|
# If the file ends in `.graphql` or `.graphqls`, treat it like a filepath
|
|
117
230
|
if definition_or_path.end_with?(".graphql") || definition_or_path.end_with?(".graphqls")
|
|
@@ -139,7 +252,12 @@ module GraphQL
|
|
|
139
252
|
graphql_definition(silence_deprecation_warning: true)
|
|
140
253
|
end
|
|
141
254
|
|
|
142
|
-
#
|
|
255
|
+
# **Returns**
|
|
256
|
+
#
|
|
257
|
+
# - `GraphQL::Subscriptions`
|
|
258
|
+
#
|
|
259
|
+
# :call-seq:
|
|
260
|
+
# subscriptions(inherited:) -> GraphQL::Subscriptions
|
|
143
261
|
def subscriptions(inherited: true)
|
|
144
262
|
defined?(@subscriptions) ? @subscriptions : (inherited ? find_inherited_value(:subscriptions, nil) : nil)
|
|
145
263
|
end
|
|
@@ -148,7 +266,12 @@ module GraphQL
|
|
|
148
266
|
@subscriptions = new_implementation
|
|
149
267
|
end
|
|
150
268
|
|
|
151
|
-
#
|
|
269
|
+
# **Parameters**
|
|
270
|
+
#
|
|
271
|
+
# - `new_mode` (`Symbol`) — If configured, this will be used when `context: { trace_mode: ... }` isn't set.
|
|
272
|
+
#
|
|
273
|
+
# :call-seq:
|
|
274
|
+
# default_trace_mode(Symbol new_mode)
|
|
152
275
|
def default_trace_mode(new_mode = NOT_CONFIGURED)
|
|
153
276
|
if !NOT_CONFIGURED.equal?(new_mode)
|
|
154
277
|
@default_trace_mode = new_mode
|
|
@@ -175,7 +298,12 @@ module GraphQL
|
|
|
175
298
|
trace_class_for(:default, build: true)
|
|
176
299
|
end
|
|
177
300
|
|
|
178
|
-
#
|
|
301
|
+
# **Returns**
|
|
302
|
+
#
|
|
303
|
+
# - `Class` — Return the trace class to use for this mode, looking one up on the superclass if this Schema doesn't have one defined.
|
|
304
|
+
#
|
|
305
|
+
# :call-seq:
|
|
306
|
+
# trace_class_for(mode, build:) -> Class
|
|
179
307
|
def trace_class_for(mode, build: false)
|
|
180
308
|
if (trace_class = own_trace_modes[mode])
|
|
181
309
|
trace_class
|
|
@@ -189,7 +317,7 @@ module GraphQL
|
|
|
189
317
|
end
|
|
190
318
|
|
|
191
319
|
# Configure `trace_class` to be used whenever `context: { trace_mode: mode_name }` is requested.
|
|
192
|
-
#
|
|
320
|
+
# `default_trace_mode` is used when no `trace_mode: ...` is requested.
|
|
193
321
|
#
|
|
194
322
|
# When a `trace_class` is added this way, it will _not_ receive other modules added with `trace_with(...)`
|
|
195
323
|
# unless `trace_mode` is explicitly given. (This class will not receive any default trace modules.)
|
|
@@ -197,9 +325,17 @@ module GraphQL
|
|
|
197
325
|
# Subclasses of the schema will use `trace_class` as a base class for this mode and those
|
|
198
326
|
# subclass also will _not_ receive default tracing modules.
|
|
199
327
|
#
|
|
200
|
-
#
|
|
201
|
-
#
|
|
202
|
-
#
|
|
328
|
+
# **Parameters**
|
|
329
|
+
#
|
|
330
|
+
# - `mode_name` (`Symbol`)
|
|
331
|
+
# - `trace_class` (`Class`) — subclass of GraphQL::Tracing::Trace
|
|
332
|
+
#
|
|
333
|
+
# **Returns**
|
|
334
|
+
#
|
|
335
|
+
# - `Object` — void
|
|
336
|
+
#
|
|
337
|
+
# :call-seq:
|
|
338
|
+
# trace_mode(Symbol mode_name, Class trace_class) -> Object
|
|
203
339
|
def trace_mode(mode_name, trace_class)
|
|
204
340
|
own_trace_modes[mode_name] = trace_class
|
|
205
341
|
nil
|
|
@@ -241,7 +377,12 @@ module GraphQL
|
|
|
241
377
|
@own_trace_modules ||= Hash.new { |h, k| h[k] = [] }
|
|
242
378
|
end
|
|
243
379
|
|
|
244
|
-
#
|
|
380
|
+
# **Returns**
|
|
381
|
+
#
|
|
382
|
+
# - `Array<Module>` — Modules added for tracing in `trace_mode`, including inherited ones
|
|
383
|
+
#
|
|
384
|
+
# :call-seq:
|
|
385
|
+
# trace_modules_for(trace_mode) -> Array[Module]
|
|
245
386
|
def trace_modules_for(trace_mode)
|
|
246
387
|
modules = own_trace_modules[trace_mode]
|
|
247
388
|
if superclass.respond_to?(:trace_modules_for)
|
|
@@ -251,21 +392,36 @@ module GraphQL
|
|
|
251
392
|
end
|
|
252
393
|
|
|
253
394
|
|
|
254
|
-
# Returns the JSON response of
|
|
255
|
-
#
|
|
256
|
-
#
|
|
395
|
+
# Returns the JSON response of [Introspection::INTROSPECTION_QUERY](rdoc-ref:Introspection::INTROSPECTION_QUERY).
|
|
396
|
+
# See [as_json](rdoc-ref:GraphQL::Schema::as_json) Return a Hash representation of the schema
|
|
397
|
+
#
|
|
398
|
+
# **Returns**
|
|
399
|
+
#
|
|
400
|
+
# - `String`
|
|
401
|
+
#
|
|
402
|
+
# :call-seq:
|
|
403
|
+
# to_json(**args) -> String
|
|
257
404
|
def to_json(**args)
|
|
258
405
|
JSON.pretty_generate(as_json(**args))
|
|
259
406
|
end
|
|
260
407
|
|
|
261
|
-
# Return the Hash response of
|
|
262
|
-
#
|
|
263
|
-
#
|
|
264
|
-
#
|
|
265
|
-
#
|
|
266
|
-
#
|
|
267
|
-
#
|
|
268
|
-
#
|
|
408
|
+
# Return the Hash response of [Introspection::INTROSPECTION_QUERY](rdoc-ref:Introspection::INTROSPECTION_QUERY).
|
|
409
|
+
#
|
|
410
|
+
# **Parameters**
|
|
411
|
+
#
|
|
412
|
+
# - `context` (`Hash`)
|
|
413
|
+
# - `include_deprecated_args` (`Boolean`) — If true, deprecated arguments will be included in the JSON response
|
|
414
|
+
# - `include_schema_description` (`Boolean`) — If true, the schema's description will be queried and included in the response
|
|
415
|
+
# - `include_is_repeatable` (`Boolean`) — If true, `isRepeatable: true|false` will be included with the schema's directives
|
|
416
|
+
# - `include_specified_by_url` (`Boolean`) — If true, scalar types' `specifiedByUrl:` will be included in the response
|
|
417
|
+
# - `include_is_one_of` (`Boolean`) — If true, `isOneOf: true|false` will be included with input objects
|
|
418
|
+
#
|
|
419
|
+
# **Returns**
|
|
420
|
+
#
|
|
421
|
+
# - `Hash` — GraphQL result
|
|
422
|
+
#
|
|
423
|
+
# :call-seq:
|
|
424
|
+
# as_json(Hash context:, bool include_deprecated_args:, bool include_schema_description:, bool include_is_repeatable:, bool include_specified_by_url:, bool include_is_one_of:) -> Hash
|
|
269
425
|
def as_json(context: {}, include_deprecated_args: true, include_schema_description: false, include_is_repeatable: false, include_specified_by_url: false, include_is_one_of: false)
|
|
270
426
|
introspection_query = Introspection.query(
|
|
271
427
|
include_deprecated_args: include_deprecated_args,
|
|
@@ -279,19 +435,39 @@ module GraphQL
|
|
|
279
435
|
end
|
|
280
436
|
|
|
281
437
|
# Return the GraphQL IDL for the schema
|
|
282
|
-
#
|
|
283
|
-
#
|
|
438
|
+
#
|
|
439
|
+
# **Parameters**
|
|
440
|
+
#
|
|
441
|
+
# - `context` (`Hash`)
|
|
442
|
+
#
|
|
443
|
+
# **Returns**
|
|
444
|
+
#
|
|
445
|
+
# - `String`
|
|
446
|
+
#
|
|
447
|
+
# :call-seq:
|
|
448
|
+
# to_definition(Hash context:) -> String
|
|
284
449
|
def to_definition(context: {})
|
|
285
450
|
GraphQL::Schema::Printer.print_schema(self, context: context)
|
|
286
451
|
end
|
|
287
452
|
|
|
288
453
|
# Return the GraphQL::Language::Document IDL AST for the schema
|
|
289
|
-
#
|
|
454
|
+
#
|
|
455
|
+
# **Returns**
|
|
456
|
+
#
|
|
457
|
+
# - `GraphQL::Language::Document`
|
|
458
|
+
#
|
|
459
|
+
# :call-seq:
|
|
460
|
+
# to_document() -> GraphQL::Language::Document
|
|
290
461
|
def to_document
|
|
291
462
|
GraphQL::Language::DocumentFromSchemaDefinition.new(self).document
|
|
292
463
|
end
|
|
293
464
|
|
|
294
|
-
#
|
|
465
|
+
# **Returns**
|
|
466
|
+
#
|
|
467
|
+
# - `String, nil`
|
|
468
|
+
#
|
|
469
|
+
# :call-seq:
|
|
470
|
+
# description(new_description) -> String | nil
|
|
295
471
|
def description(new_description = nil)
|
|
296
472
|
if new_description
|
|
297
473
|
@description = new_description
|
|
@@ -315,8 +491,17 @@ module GraphQL
|
|
|
315
491
|
end
|
|
316
492
|
|
|
317
493
|
# Add `plugin` to this schema
|
|
318
|
-
#
|
|
319
|
-
#
|
|
494
|
+
#
|
|
495
|
+
# **Parameters**
|
|
496
|
+
#
|
|
497
|
+
# - `plugin` (`#use`) — A Schema plugin
|
|
498
|
+
#
|
|
499
|
+
# **Returns**
|
|
500
|
+
#
|
|
501
|
+
# - `Object` — void
|
|
502
|
+
#
|
|
503
|
+
# :call-seq:
|
|
504
|
+
# use(#use plugin, **kwargs) -> Object
|
|
320
505
|
def use(plugin, **kwargs)
|
|
321
506
|
if !kwargs.empty?
|
|
322
507
|
plugin.use(self, **kwargs)
|
|
@@ -336,9 +521,15 @@ module GraphQL
|
|
|
336
521
|
@null_context || GraphQL::Query::NullContext.instance
|
|
337
522
|
end
|
|
338
523
|
|
|
339
|
-
# Build a map of `{ name => type }` and return it
|
|
340
|
-
#
|
|
341
|
-
#
|
|
524
|
+
# Build a map of `{ name => type }` and return it.
|
|
525
|
+
# `get_type` is more efficient for finding _one type_ by name, because it doesn't merge hashes.
|
|
526
|
+
#
|
|
527
|
+
# **Returns**
|
|
528
|
+
#
|
|
529
|
+
# - `Hash<String => Class>` — A dictionary of type classes by their GraphQL name
|
|
530
|
+
#
|
|
531
|
+
# :call-seq:
|
|
532
|
+
# types(context) -> Hash[String, Class]
|
|
342
533
|
def types(context = null_context)
|
|
343
534
|
if use_visibility_profile?
|
|
344
535
|
types = Visibility::Profile.from_context(context, self)
|
|
@@ -368,10 +559,18 @@ module GraphQL
|
|
|
368
559
|
visible_types
|
|
369
560
|
end
|
|
370
561
|
|
|
371
|
-
#
|
|
372
|
-
#
|
|
373
|
-
#
|
|
374
|
-
#
|
|
562
|
+
# **Parameters**
|
|
563
|
+
#
|
|
564
|
+
# - `type_name` (`String`)
|
|
565
|
+
# - `context` (`GraphQL::Query::Context`) — Used for filtering definitions at query-time
|
|
566
|
+
# - `use_visibility_profile` — Private, for migration to [Schema::Visibility](rdoc-ref:Schema::Visibility)
|
|
567
|
+
#
|
|
568
|
+
# **Returns**
|
|
569
|
+
#
|
|
570
|
+
# - `Module, nil` — A type, or nil if there's no type called `type_name`
|
|
571
|
+
#
|
|
572
|
+
# :call-seq:
|
|
573
|
+
# get_type(String type_name, GraphQL::Query::Context context, use_visibility_profile) -> Module | nil
|
|
375
574
|
def get_type(type_name, context = null_context, use_visibility_profile = use_visibility_profile?)
|
|
376
575
|
if use_visibility_profile
|
|
377
576
|
profile = Visibility::Profile.from_context(context, self)
|
|
@@ -411,15 +610,24 @@ module GraphQL
|
|
|
411
610
|
(superclass.respond_to?(:get_type) ? superclass.get_type(type_name, context, use_visibility_profile) : nil)
|
|
412
611
|
end
|
|
413
612
|
|
|
414
|
-
#
|
|
613
|
+
# **Returns**
|
|
614
|
+
#
|
|
615
|
+
# - `Boolean` — Does this schema have _any_ definition for a type named `type_name`, regardless of visibility?
|
|
616
|
+
#
|
|
617
|
+
# :call-seq:
|
|
618
|
+
# has_defined_type?(type_name) -> bool
|
|
415
619
|
def has_defined_type?(type_name)
|
|
416
620
|
own_types.key?(type_name) || introspection_system.types.key?(type_name) || (superclass.respond_to?(:has_defined_type?) ? superclass.has_defined_type?(type_name) : false)
|
|
417
621
|
end
|
|
418
622
|
|
|
419
|
-
#
|
|
420
|
-
attr_writer :connections
|
|
623
|
+
attr_writer :connections # :nodoc:
|
|
421
624
|
|
|
422
|
-
#
|
|
625
|
+
# **Returns**
|
|
626
|
+
#
|
|
627
|
+
# - `GraphQL::Pagination::Connections` — if installed
|
|
628
|
+
#
|
|
629
|
+
# :call-seq:
|
|
630
|
+
# connections() -> GraphQL::Pagination::Connections
|
|
423
631
|
def connections
|
|
424
632
|
if defined?(@connections)
|
|
425
633
|
@connections
|
|
@@ -435,14 +643,27 @@ module GraphQL
|
|
|
435
643
|
end
|
|
436
644
|
end
|
|
437
645
|
|
|
438
|
-
# Get or set the root `query
|
|
646
|
+
# Get or set the root `query` object for this schema.
|
|
439
647
|
#
|
|
440
|
-
#
|
|
441
|
-
# query { Types::Query }
|
|
648
|
+
# **Examples**
|
|
442
649
|
#
|
|
443
|
-
#
|
|
444
|
-
#
|
|
445
|
-
#
|
|
650
|
+
# **Example: Using `Types::Query` as the entry-point**
|
|
651
|
+
#
|
|
652
|
+
# ```ruby
|
|
653
|
+
# query { Types::Query }
|
|
654
|
+
# ```
|
|
655
|
+
#
|
|
656
|
+
# **Parameters**
|
|
657
|
+
#
|
|
658
|
+
# - `new_query_object` (`Class<GraphQL::Schema::Object>`) — The root type to use for queries
|
|
659
|
+
# - `lazy_load_block` — If a block is given, then it will be called when GraphQL-Ruby needs the root query type.
|
|
660
|
+
#
|
|
661
|
+
# **Returns**
|
|
662
|
+
#
|
|
663
|
+
# - `Class<GraphQL::Schema::Object>, nil` — The configured query root type, if there is one.
|
|
664
|
+
#
|
|
665
|
+
# :call-seq:
|
|
666
|
+
# query(Class[GraphQL::Schema::Object] new_query_object, &lazy_load_block) -> Class[GraphQL::Schema::Object] | nil
|
|
446
667
|
def query(new_query_object = nil, &lazy_load_block)
|
|
447
668
|
if new_query_object || block_given?
|
|
448
669
|
if @query_object
|
|
@@ -474,14 +695,27 @@ module GraphQL
|
|
|
474
695
|
end
|
|
475
696
|
end
|
|
476
697
|
|
|
477
|
-
# Get or set the root `mutation
|
|
698
|
+
# Get or set the root `mutation` object for this schema.
|
|
699
|
+
#
|
|
700
|
+
# **Examples**
|
|
701
|
+
#
|
|
702
|
+
# **Example: Using `Types::Mutation` as the entry-point**
|
|
703
|
+
#
|
|
704
|
+
# ```ruby
|
|
705
|
+
# mutation { Types::Mutation }
|
|
706
|
+
# ```
|
|
707
|
+
#
|
|
708
|
+
# **Parameters**
|
|
709
|
+
#
|
|
710
|
+
# - `new_mutation_object` (`Class<GraphQL::Schema::Object>`) — The root type to use for mutations
|
|
711
|
+
# - `lazy_load_block` — If a block is given, then it will be called when GraphQL-Ruby needs the root mutation type.
|
|
478
712
|
#
|
|
479
|
-
#
|
|
480
|
-
# mutation { Types::Mutation }
|
|
713
|
+
# **Returns**
|
|
481
714
|
#
|
|
482
|
-
#
|
|
483
|
-
#
|
|
484
|
-
#
|
|
715
|
+
# - `Class<GraphQL::Schema::Object>, nil` — The configured mutation root type, if there is one.
|
|
716
|
+
#
|
|
717
|
+
# :call-seq:
|
|
718
|
+
# mutation(Class[GraphQL::Schema::Object] new_mutation_object, &lazy_load_block) -> Class[GraphQL::Schema::Object] | nil
|
|
485
719
|
def mutation(new_mutation_object = nil, &lazy_load_block)
|
|
486
720
|
if new_mutation_object || block_given?
|
|
487
721
|
if @mutation_object
|
|
@@ -513,14 +747,27 @@ module GraphQL
|
|
|
513
747
|
end
|
|
514
748
|
end
|
|
515
749
|
|
|
516
|
-
# Get or set the root `subscription
|
|
750
|
+
# Get or set the root `subscription` object for this schema.
|
|
751
|
+
#
|
|
752
|
+
# **Examples**
|
|
753
|
+
#
|
|
754
|
+
# **Example: Using `Types::Subscription` as the entry-point**
|
|
755
|
+
#
|
|
756
|
+
# ```ruby
|
|
757
|
+
# subscription { Types::Subscription }
|
|
758
|
+
# ```
|
|
759
|
+
#
|
|
760
|
+
# **Parameters**
|
|
761
|
+
#
|
|
762
|
+
# - `new_subscription_object` (`Class<GraphQL::Schema::Object>`) — The root type to use for subscriptions
|
|
763
|
+
# - `lazy_load_block` — If a block is given, then it will be called when GraphQL-Ruby needs the root subscription type.
|
|
517
764
|
#
|
|
518
|
-
#
|
|
519
|
-
# subscription { Types::Subscription }
|
|
765
|
+
# **Returns**
|
|
520
766
|
#
|
|
521
|
-
#
|
|
522
|
-
#
|
|
523
|
-
#
|
|
767
|
+
# - `Class<GraphQL::Schema::Object>, nil` — The configured subscription root type, if there is one.
|
|
768
|
+
#
|
|
769
|
+
# :call-seq:
|
|
770
|
+
# subscription(Class[GraphQL::Schema::Object] new_subscription_object, &lazy_load_block) -> Class[GraphQL::Schema::Object] | nil
|
|
524
771
|
def subscription(new_subscription_object = nil, &lazy_load_block)
|
|
525
772
|
if new_subscription_object || block_given?
|
|
526
773
|
if @subscription_object
|
|
@@ -555,8 +802,7 @@ module GraphQL
|
|
|
555
802
|
end
|
|
556
803
|
end
|
|
557
804
|
|
|
558
|
-
#
|
|
559
|
-
def root_type_for_operation(operation)
|
|
805
|
+
def root_type_for_operation(operation) # :nodoc:
|
|
560
806
|
case operation
|
|
561
807
|
when "query"
|
|
562
808
|
query
|
|
@@ -569,7 +815,12 @@ module GraphQL
|
|
|
569
815
|
end
|
|
570
816
|
end
|
|
571
817
|
|
|
572
|
-
#
|
|
818
|
+
# **Returns**
|
|
819
|
+
#
|
|
820
|
+
# - `Array<Class>` — The root types (query, mutation, subscription) defined for this schema
|
|
821
|
+
#
|
|
822
|
+
# :call-seq:
|
|
823
|
+
# root_types() -> Array[Class]
|
|
573
824
|
def root_types
|
|
574
825
|
if use_visibility_profile?
|
|
575
826
|
[query, mutation, subscription].compact
|
|
@@ -578,8 +829,7 @@ module GraphQL
|
|
|
578
829
|
end
|
|
579
830
|
end
|
|
580
831
|
|
|
581
|
-
#
|
|
582
|
-
def warden_class
|
|
832
|
+
def warden_class # :nodoc:
|
|
583
833
|
if defined?(@warden_class)
|
|
584
834
|
@warden_class
|
|
585
835
|
elsif superclass.respond_to?(:warden_class)
|
|
@@ -589,11 +839,9 @@ module GraphQL
|
|
|
589
839
|
end
|
|
590
840
|
end
|
|
591
841
|
|
|
592
|
-
#
|
|
593
|
-
attr_writer :warden_class
|
|
842
|
+
attr_writer :warden_class # :nodoc:
|
|
594
843
|
|
|
595
|
-
#
|
|
596
|
-
def visibility_profile_class
|
|
844
|
+
def visibility_profile_class # :nodoc:
|
|
597
845
|
if defined?(@visibility_profile_class)
|
|
598
846
|
@visibility_profile_class
|
|
599
847
|
elsif superclass.respond_to?(:visibility_profile_class)
|
|
@@ -603,12 +851,9 @@ module GraphQL
|
|
|
603
851
|
end
|
|
604
852
|
end
|
|
605
853
|
|
|
606
|
-
#
|
|
607
|
-
|
|
608
|
-
#
|
|
609
|
-
attr_accessor :visibility
|
|
610
|
-
# @api private
|
|
611
|
-
def use_visibility_profile?
|
|
854
|
+
attr_writer :visibility_profile_class, :use_visibility_profile # :nodoc:
|
|
855
|
+
attr_accessor :visibility # :nodoc:
|
|
856
|
+
def use_visibility_profile? # :nodoc:
|
|
612
857
|
if defined?(@use_visibility_profile)
|
|
613
858
|
@use_visibility_profile
|
|
614
859
|
elsif superclass.respond_to?(:use_visibility_profile?)
|
|
@@ -618,11 +863,19 @@ module GraphQL
|
|
|
618
863
|
end
|
|
619
864
|
end
|
|
620
865
|
|
|
621
|
-
#
|
|
622
|
-
#
|
|
623
|
-
#
|
|
624
|
-
#
|
|
625
|
-
#
|
|
866
|
+
# **Parameters**
|
|
867
|
+
#
|
|
868
|
+
# - `type` (`Module`) — The type definition whose possible types you want to see
|
|
869
|
+
# - `context` (`GraphQL::Query::Context`) — used for filtering visible possible types at runtime
|
|
870
|
+
# - `use_visibility_profile` — Private, for migration to [Schema::Visibility](rdoc-ref:Schema::Visibility)
|
|
871
|
+
#
|
|
872
|
+
# **Returns**
|
|
873
|
+
#
|
|
874
|
+
# - `Hash<String, Module>` — All possible types, if no `type` is given.
|
|
875
|
+
# - `Array<Module>` — Possible types for `type`, if it's given.
|
|
876
|
+
#
|
|
877
|
+
# :call-seq:
|
|
878
|
+
# possible_types(Module type, GraphQL::Query::Context context, use_visibility_profile) -> Hash[String, Module] | Array[Module]
|
|
626
879
|
def possible_types(type = nil, context = null_context, use_visibility_profile = use_visibility_profile?)
|
|
627
880
|
if use_visibility_profile
|
|
628
881
|
if type
|
|
@@ -674,9 +927,8 @@ module GraphQL
|
|
|
674
927
|
end
|
|
675
928
|
end
|
|
676
929
|
|
|
677
|
-
#
|
|
678
|
-
#
|
|
679
|
-
def dataloader_class
|
|
930
|
+
# See [GraphQL::Dataloader](rdoc-ref:GraphQL::Dataloader).
|
|
931
|
+
def dataloader_class # :nodoc:
|
|
680
932
|
@dataloader_class || GraphQL::Dataloader::NullDataloader
|
|
681
933
|
end
|
|
682
934
|
|
|
@@ -749,8 +1001,17 @@ module GraphQL
|
|
|
749
1001
|
end
|
|
750
1002
|
|
|
751
1003
|
# Pass a custom introspection module here to use it for this schema.
|
|
752
|
-
#
|
|
753
|
-
#
|
|
1004
|
+
#
|
|
1005
|
+
# **Parameters**
|
|
1006
|
+
#
|
|
1007
|
+
# - `new_introspection_namespace` (`Module`) — If given, use this module for custom introspection on the schema
|
|
1008
|
+
#
|
|
1009
|
+
# **Returns**
|
|
1010
|
+
#
|
|
1011
|
+
# - `Module, nil` — The configured namespace, if there is one
|
|
1012
|
+
#
|
|
1013
|
+
# :call-seq:
|
|
1014
|
+
# introspection(Module new_introspection_namespace) -> Module | nil
|
|
754
1015
|
def introspection(new_introspection_namespace = nil)
|
|
755
1016
|
if new_introspection_namespace
|
|
756
1017
|
@introspection = new_introspection_namespace
|
|
@@ -764,7 +1025,12 @@ module GraphQL
|
|
|
764
1025
|
end
|
|
765
1026
|
end
|
|
766
1027
|
|
|
767
|
-
#
|
|
1028
|
+
# **Returns**
|
|
1029
|
+
#
|
|
1030
|
+
# - `Schema::IntrospectionSystem` — Based on [introspection](rdoc-ref:introspection)
|
|
1031
|
+
#
|
|
1032
|
+
# :call-seq:
|
|
1033
|
+
# introspection_system() -> Schema::IntrospectionSystem
|
|
768
1034
|
def introspection_system
|
|
769
1035
|
if !@introspection_system
|
|
770
1036
|
@introspection_system = Schema::IntrospectionSystem.new(self)
|
|
@@ -790,7 +1056,13 @@ module GraphQL
|
|
|
790
1056
|
|
|
791
1057
|
# A limit on the number of tokens to accept on incoming query strings.
|
|
792
1058
|
# Use this to prevent parsing maliciously-large query strings.
|
|
793
|
-
#
|
|
1059
|
+
#
|
|
1060
|
+
# **Returns**
|
|
1061
|
+
#
|
|
1062
|
+
# - `nil, Integer`
|
|
1063
|
+
#
|
|
1064
|
+
# :call-seq:
|
|
1065
|
+
# max_query_string_tokens(new_max_tokens) -> nil | Integer
|
|
794
1066
|
def max_query_string_tokens(new_max_tokens = NOT_CONFIGURED)
|
|
795
1067
|
if NOT_CONFIGURED.equal?(new_max_tokens)
|
|
796
1068
|
defined?(@max_query_string_tokens) ? @max_query_string_tokens : find_inherited_value(:max_query_string_tokens)
|
|
@@ -856,8 +1128,17 @@ module GraphQL
|
|
|
856
1128
|
end
|
|
857
1129
|
|
|
858
1130
|
# Validate a query string according to this schema.
|
|
859
|
-
#
|
|
860
|
-
#
|
|
1131
|
+
#
|
|
1132
|
+
# **Parameters**
|
|
1133
|
+
#
|
|
1134
|
+
# - `string_or_document` (`String, GraphQL::Language::Nodes::Document`)
|
|
1135
|
+
#
|
|
1136
|
+
# **Returns**
|
|
1137
|
+
#
|
|
1138
|
+
# - `Array<GraphQL::StaticValidation::Error >`
|
|
1139
|
+
#
|
|
1140
|
+
# :call-seq:
|
|
1141
|
+
# validate(String | GraphQL::Language::Nodes::Document string_or_document, rules:, context:) -> Array[GraphQL::StaticValidation::Error]
|
|
861
1142
|
def validate(string_or_document, rules: nil, context: nil)
|
|
862
1143
|
doc = if string_or_document.is_a?(String)
|
|
863
1144
|
GraphQL.parse(string_or_document, max_tokens: max_query_string_tokens)
|
|
@@ -872,7 +1153,12 @@ module GraphQL
|
|
|
872
1153
|
res[:errors]
|
|
873
1154
|
end
|
|
874
1155
|
|
|
875
|
-
#
|
|
1156
|
+
# **Parameters**
|
|
1157
|
+
#
|
|
1158
|
+
# - `new_query_class` (`Class<GraphQL::Query>`) — A subclass to use when executing queries
|
|
1159
|
+
#
|
|
1160
|
+
# :call-seq:
|
|
1161
|
+
# query_class(Class[GraphQL::Query] new_query_class)
|
|
876
1162
|
def query_class(new_query_class = NOT_CONFIGURED)
|
|
877
1163
|
if NOT_CONFIGURED.equal?(new_query_class)
|
|
878
1164
|
@query_class || (superclass.respond_to?(:query_class) ? superclass.query_class : GraphQL::Query)
|
|
@@ -992,8 +1278,16 @@ module GraphQL
|
|
|
992
1278
|
end
|
|
993
1279
|
end
|
|
994
1280
|
|
|
995
|
-
#
|
|
996
|
-
#
|
|
1281
|
+
# **Parameters**
|
|
1282
|
+
#
|
|
1283
|
+
# - `new_extra_types` (`Module`) — Type definitions to include in printing and introspection, even though they aren't referenced in the schema
|
|
1284
|
+
#
|
|
1285
|
+
# **Returns**
|
|
1286
|
+
#
|
|
1287
|
+
# - `Array<Module>` — Type definitions added to this schema
|
|
1288
|
+
#
|
|
1289
|
+
# :call-seq:
|
|
1290
|
+
# extra_types(Module *new_extra_types) -> Array[Module]
|
|
997
1291
|
def extra_types(*new_extra_types)
|
|
998
1292
|
if !new_extra_types.empty?
|
|
999
1293
|
new_extra_types = new_extra_types.flatten
|
|
@@ -1017,8 +1311,16 @@ module GraphQL
|
|
|
1017
1311
|
# This method must be used when an object type is connected to the schema as an interface implementor but
|
|
1018
1312
|
# not as a return type of a field. In that case, if the object type isn't registered here, GraphQL-Ruby won't be able to find it.
|
|
1019
1313
|
#
|
|
1020
|
-
#
|
|
1021
|
-
#
|
|
1314
|
+
# **Parameters**
|
|
1315
|
+
#
|
|
1316
|
+
# - `new_orphan_types` (`Array<Class<GraphQL::Schema::Object>>`) — Object types to register as implementations of interfaces in the schema.
|
|
1317
|
+
#
|
|
1318
|
+
# **Returns**
|
|
1319
|
+
#
|
|
1320
|
+
# - `Array<Class<GraphQL::Schema::Object>>` — All previously-registered orphan types for this schema
|
|
1321
|
+
#
|
|
1322
|
+
# :call-seq:
|
|
1323
|
+
# orphan_types(Array[Class[GraphQL::Schema::Object]] *new_orphan_types) -> Array[Class[GraphQL::Schema::Object]]
|
|
1022
1324
|
def orphan_types(*new_orphan_types)
|
|
1023
1325
|
if !new_orphan_types.empty?
|
|
1024
1326
|
new_orphan_types = new_orphan_types.flatten
|
|
@@ -1067,7 +1369,12 @@ module GraphQL
|
|
|
1067
1369
|
end
|
|
1068
1370
|
|
|
1069
1371
|
|
|
1070
|
-
#
|
|
1372
|
+
# **Parameters**
|
|
1373
|
+
#
|
|
1374
|
+
# - `new_default_logger` (`#log`) — Something to use for logging messages
|
|
1375
|
+
#
|
|
1376
|
+
# :call-seq:
|
|
1377
|
+
# default_logger(#log new_default_logger)
|
|
1071
1378
|
def default_logger(new_default_logger = NOT_CONFIGURED)
|
|
1072
1379
|
if NOT_CONFIGURED.equal?(new_default_logger)
|
|
1073
1380
|
if defined?(@default_logger)
|
|
@@ -1088,8 +1395,16 @@ module GraphQL
|
|
|
1088
1395
|
end
|
|
1089
1396
|
end
|
|
1090
1397
|
|
|
1091
|
-
#
|
|
1092
|
-
#
|
|
1398
|
+
# **Parameters**
|
|
1399
|
+
#
|
|
1400
|
+
# - `context` (`GraphQL::Query::Context, nil`)
|
|
1401
|
+
#
|
|
1402
|
+
# **Returns**
|
|
1403
|
+
#
|
|
1404
|
+
# - `Logger` — A logger to use for this context configuration, falling back to [.default_logger](rdoc-ref:.default_logger)
|
|
1405
|
+
#
|
|
1406
|
+
# :call-seq:
|
|
1407
|
+
# logger_for(GraphQL::Query::Context | nil context) -> Logger
|
|
1093
1408
|
def logger_for(context)
|
|
1094
1409
|
if context && context[:logger] == false
|
|
1095
1410
|
Logger.new(IO::NULL)
|
|
@@ -1100,7 +1415,12 @@ module GraphQL
|
|
|
1100
1415
|
end
|
|
1101
1416
|
end
|
|
1102
1417
|
|
|
1103
|
-
#
|
|
1418
|
+
# **Parameters**
|
|
1419
|
+
#
|
|
1420
|
+
# - `new_context_class` (`Class<GraphQL::Query::Context>`) — A subclass to use when executing queries
|
|
1421
|
+
#
|
|
1422
|
+
# :call-seq:
|
|
1423
|
+
# context_class(Class[GraphQL::Query::Context] new_context_class)
|
|
1104
1424
|
def context_class(new_context_class = nil)
|
|
1105
1425
|
if new_context_class
|
|
1106
1426
|
@context_class = new_context_class
|
|
@@ -1111,18 +1431,34 @@ module GraphQL
|
|
|
1111
1431
|
|
|
1112
1432
|
# Register a handler for errors raised during execution. The handlers can return a new value or raise a new error.
|
|
1113
1433
|
#
|
|
1114
|
-
#
|
|
1115
|
-
#
|
|
1116
|
-
#
|
|
1117
|
-
#
|
|
1118
|
-
#
|
|
1119
|
-
#
|
|
1120
|
-
#
|
|
1121
|
-
#
|
|
1122
|
-
#
|
|
1123
|
-
#
|
|
1124
|
-
#
|
|
1125
|
-
#
|
|
1434
|
+
# **Examples**
|
|
1435
|
+
#
|
|
1436
|
+
# **Example: Handling "not found" with a client-facing error**
|
|
1437
|
+
#
|
|
1438
|
+
# ```ruby
|
|
1439
|
+
# rescue_from(ActiveRecord::NotFound) { raise GraphQL::ExecutionError, "An object could not be found" }
|
|
1440
|
+
# ```
|
|
1441
|
+
#
|
|
1442
|
+
# **Parameters**
|
|
1443
|
+
#
|
|
1444
|
+
# - `err_classes` (`Array<StandardError>`) — Classes which should be rescued by `handler_block`
|
|
1445
|
+
# - `handler_block` — The code to run when one of those errors is raised during execution
|
|
1446
|
+
#
|
|
1447
|
+
# **Yields**
|
|
1448
|
+
#
|
|
1449
|
+
# - `error` (`StandardError`) — An instance of one of the configured `err_classes`
|
|
1450
|
+
# - `object` (`Object`) — The current application object in the query when the error was raised
|
|
1451
|
+
# - `arguments` (`GraphQL::Query::Arguments`) — The current field arguments when the error was raised
|
|
1452
|
+
# - `context` (`GraphQL::Query::Context`) — The context for the currently-running operation
|
|
1453
|
+
# - `Object` — Some object to use in the place where this error was raised
|
|
1454
|
+
#
|
|
1455
|
+
# **Raises**
|
|
1456
|
+
#
|
|
1457
|
+
# - `GraphQL::ExecutionError` — In the handler, raise to add a client-facing error to the response
|
|
1458
|
+
# - `StandardError` — In the handler, raise to crash the query with a developer-facing error
|
|
1459
|
+
#
|
|
1460
|
+
# :call-seq:
|
|
1461
|
+
# rescue_from(Array[StandardError] *err_classes, &handler_block)
|
|
1126
1462
|
def rescue_from(*err_classes, &handler_block)
|
|
1127
1463
|
err_classes.each do |err_class|
|
|
1128
1464
|
Execution::Errors.register_rescue_from(err_class, error_handlers[:subclass_handlers], handler_block)
|
|
@@ -1146,11 +1482,9 @@ module GraphQL
|
|
|
1146
1482
|
end
|
|
1147
1483
|
end
|
|
1148
1484
|
|
|
1149
|
-
#
|
|
1150
|
-
attr_accessor :using_backtrace
|
|
1485
|
+
attr_accessor :using_backtrace # :nodoc:
|
|
1151
1486
|
|
|
1152
|
-
#
|
|
1153
|
-
def handle_or_reraise(context, err, object: context[:current_object], arguments: context[:current_arguments], field: context[:current_field])
|
|
1487
|
+
def handle_or_reraise(context, err, object: context[:current_object], arguments: context[:current_arguments], field: context[:current_field]) # :nodoc:
|
|
1154
1488
|
handler = Execution::Errors.find_handler_for(self, err.class)
|
|
1155
1489
|
if handler
|
|
1156
1490
|
arguments = arguments.respond_to?(:keyword_arguments) ? arguments.keyword_arguments : arguments
|
|
@@ -1196,20 +1530,34 @@ module GraphQL
|
|
|
1196
1530
|
|
|
1197
1531
|
# GraphQL-Ruby calls this method during execution when it needs the application to determine the type to use for an object.
|
|
1198
1532
|
#
|
|
1199
|
-
# Usually, this object was returned from a field whose return type is an
|
|
1200
|
-
# But this method is called in other cases, too -- for example, when
|
|
1533
|
+
# Usually, this object was returned from a field whose return type is an [GraphQL::Schema::Interface](rdoc-ref:GraphQL::Schema::Interface) or a [GraphQL::Schema::Union](rdoc-ref:GraphQL::Schema::Union).
|
|
1534
|
+
# But this method is called in other cases, too -- for example, when [GraphQL::Schema::Argument#loads](rdoc-ref:GraphQL::Schema::Argument#loads) cases an object to be directly loaded from the database.
|
|
1201
1535
|
#
|
|
1202
|
-
#
|
|
1203
|
-
#
|
|
1204
|
-
#
|
|
1205
|
-
#
|
|
1206
|
-
#
|
|
1207
|
-
#
|
|
1536
|
+
# **Examples**
|
|
1537
|
+
#
|
|
1538
|
+
# **Example: Returning a GraphQL type based on the object's class name**
|
|
1539
|
+
#
|
|
1540
|
+
# ```ruby
|
|
1541
|
+
# class MySchema < GraphQL::Schema
|
|
1542
|
+
# def resolve_type(_abs_type, object, _context)
|
|
1543
|
+
# graphql_type_name = "Types::#{object.class.name}Type"
|
|
1544
|
+
# graphql_type_name.constantize # If this raises a NameError, then come implement special cases in this method
|
|
1208
1545
|
# end
|
|
1209
|
-
#
|
|
1210
|
-
#
|
|
1211
|
-
#
|
|
1212
|
-
#
|
|
1546
|
+
# end
|
|
1547
|
+
# ```
|
|
1548
|
+
#
|
|
1549
|
+
# **Parameters**
|
|
1550
|
+
#
|
|
1551
|
+
# - `abstract_type` (`Class, Module, nil`) — The Interface or Union type which is being resolved, if there is one
|
|
1552
|
+
# - `application_object` (`Object`) — The object returned from a field whose type must be determined
|
|
1553
|
+
# - `context` (`GraphQL::Query::Context`) — The query context for the currently-executing query
|
|
1554
|
+
#
|
|
1555
|
+
# **Returns**
|
|
1556
|
+
#
|
|
1557
|
+
# - `Class<GraphQL::Schema::Object>` — The Object type definition to use for `obj`
|
|
1558
|
+
#
|
|
1559
|
+
# :call-seq:
|
|
1560
|
+
# resolve_type(Class | Module | nil abstract_type, Object application_object, GraphQL::Query::Context context) -> Class[GraphQL::Schema::Object]
|
|
1213
1561
|
def resolve_type(abstract_type, application_object, context)
|
|
1214
1562
|
raise GraphQL::RequiredImplementationMissingError, "#{self.name}.resolve_type(abstract_type, application_object, context) must be implemented to use Union types, Interface types, `loads:`, or `run_partials` (tried to resolve: #{abstract_type.name})"
|
|
1215
1563
|
end
|
|
@@ -1238,32 +1586,60 @@ module GraphQL
|
|
|
1238
1586
|
# Fetch an object based on an incoming ID and the current context. This method should return an object
|
|
1239
1587
|
# from your application, or return `nil` if there is no object or the object shouldn't be available to this operation.
|
|
1240
1588
|
#
|
|
1241
|
-
#
|
|
1242
|
-
#
|
|
1243
|
-
#
|
|
1244
|
-
#
|
|
1245
|
-
#
|
|
1246
|
-
#
|
|
1247
|
-
#
|
|
1248
|
-
#
|
|
1249
|
-
#
|
|
1589
|
+
# See [id_from_object](rdoc-ref:id_from_object) which produces these IDs
|
|
1590
|
+
#
|
|
1591
|
+
# **Examples**
|
|
1592
|
+
#
|
|
1593
|
+
# **Example: Fetching an object with Rails's GlobalID**
|
|
1594
|
+
#
|
|
1595
|
+
# ```ruby
|
|
1596
|
+
# def self.object_from_id(object_id, _context)
|
|
1597
|
+
# GlobalID.find(global_id)
|
|
1598
|
+
# # TODO: use `context[:current_user]` to determine if this object is authorized.
|
|
1599
|
+
# end
|
|
1600
|
+
# ```
|
|
1601
|
+
#
|
|
1602
|
+
# **Parameters**
|
|
1603
|
+
#
|
|
1604
|
+
# - `object_id` (`String`) — The ID to fetch an object for. This may be client-provided (as in `node(id: ...)` or `loads:`) or previously stored by the schema (eg, by the `ObjectCache`)
|
|
1605
|
+
# - `context` (`GraphQL::Query::Context`) — The context for the currently-executing operation
|
|
1606
|
+
#
|
|
1607
|
+
# **Returns**
|
|
1608
|
+
#
|
|
1609
|
+
# - `Object, nil` — The application which `object_id` references, or `nil` if there is no object or the current operation shouldn't have access to the object
|
|
1610
|
+
#
|
|
1611
|
+
# :call-seq:
|
|
1612
|
+
# object_from_id(String object_id, GraphQL::Query::Context context) -> Object | nil
|
|
1250
1613
|
def object_from_id(object_id, context)
|
|
1251
1614
|
raise GraphQL::RequiredImplementationMissingError, "#{self.name}.object_from_id(object_id, context) must be implemented to load by ID (tried to load from id `#{object_id}`)"
|
|
1252
1615
|
end
|
|
1253
1616
|
|
|
1254
|
-
# Return a stable ID string for `object` so that it can be refetched later, using
|
|
1617
|
+
# Return a stable ID string for `object` so that it can be refetched later, using [.object_from_id](rdoc-ref:.object_from_id).
|
|
1255
1618
|
#
|
|
1256
1619
|
# [GlobalID](https://github.com/rails/globalid) and [SQIDs](https://sqids.org/ruby) can both be used to create IDs.
|
|
1257
1620
|
#
|
|
1258
|
-
#
|
|
1259
|
-
#
|
|
1260
|
-
#
|
|
1261
|
-
#
|
|
1621
|
+
# **Examples**
|
|
1622
|
+
#
|
|
1623
|
+
# **Example: Using Rails's GlobalID to generate IDs**
|
|
1624
|
+
#
|
|
1625
|
+
# ```ruby
|
|
1626
|
+
# def self.id_from_object(application_object, graphql_type, context)
|
|
1627
|
+
# application_object.to_gid_param
|
|
1628
|
+
# end
|
|
1629
|
+
# ```
|
|
1630
|
+
#
|
|
1631
|
+
# **Parameters**
|
|
1632
|
+
#
|
|
1633
|
+
# - `application_object` (`Object`) — Some object encountered by GraphQL-Ruby while running a query
|
|
1634
|
+
# - `graphql_type` (`Class, Module`) — The type that GraphQL-Ruby is using for `application_object` during this query
|
|
1635
|
+
# - `context` (`GraphQL::Query::Context`) — The context for the operation that is currently running
|
|
1636
|
+
#
|
|
1637
|
+
# **Returns**
|
|
1262
1638
|
#
|
|
1263
|
-
#
|
|
1264
|
-
#
|
|
1265
|
-
#
|
|
1266
|
-
#
|
|
1639
|
+
# - `String` — A stable identifier which can be passed to [.object_from_id](rdoc-ref:.object_from_id) later to re-fetch `application_object`
|
|
1640
|
+
#
|
|
1641
|
+
# :call-seq:
|
|
1642
|
+
# id_from_object(Object application_object, Class | Module graphql_type, GraphQL::Query::Context context) -> String
|
|
1267
1643
|
def id_from_object(application_object, graphql_type, context)
|
|
1268
1644
|
raise GraphQL::RequiredImplementationMissingError, "#{self.name}.id_from_object(application_object, graphql_type, context) must be implemented to create global ids (tried to create an id for `#{application_object.inspect}`)"
|
|
1269
1645
|
end
|
|
@@ -1295,11 +1671,19 @@ module GraphQL
|
|
|
1295
1671
|
# unauthorized object (accessible as `unauthorized_error.object`). If an
|
|
1296
1672
|
# error is raised, then `nil` will be used.
|
|
1297
1673
|
#
|
|
1298
|
-
# If you want to add an error to the `"errors"` key, raise a
|
|
1674
|
+
# If you want to add an error to the `"errors"` key, raise a [GraphQL::ExecutionError](rdoc-ref:GraphQL::ExecutionError)
|
|
1299
1675
|
# in this hook.
|
|
1300
1676
|
#
|
|
1301
|
-
#
|
|
1302
|
-
#
|
|
1677
|
+
# **Parameters**
|
|
1678
|
+
#
|
|
1679
|
+
# - `unauthorized_error` (`GraphQL::UnauthorizedError`)
|
|
1680
|
+
#
|
|
1681
|
+
# **Returns**
|
|
1682
|
+
#
|
|
1683
|
+
# - `Object` — The returned object will be put in the GraphQL response
|
|
1684
|
+
#
|
|
1685
|
+
# :call-seq:
|
|
1686
|
+
# unauthorized_object(GraphQL::UnauthorizedError unauthorized_error) -> Object
|
|
1303
1687
|
def unauthorized_object(unauthorized_error)
|
|
1304
1688
|
nil
|
|
1305
1689
|
end
|
|
@@ -1311,11 +1695,19 @@ module GraphQL
|
|
|
1311
1695
|
# Whatever value is returned from this method will be used instead of the
|
|
1312
1696
|
# unauthorized field . If an error is raised, then `nil` will be used.
|
|
1313
1697
|
#
|
|
1314
|
-
# If you want to add an error to the `"errors"` key, raise a
|
|
1698
|
+
# If you want to add an error to the `"errors"` key, raise a [GraphQL::ExecutionError](rdoc-ref:GraphQL::ExecutionError)
|
|
1315
1699
|
# in this hook.
|
|
1316
1700
|
#
|
|
1317
|
-
#
|
|
1318
|
-
#
|
|
1701
|
+
# **Parameters**
|
|
1702
|
+
#
|
|
1703
|
+
# - `unauthorized_error` (`GraphQL::UnauthorizedFieldError`)
|
|
1704
|
+
#
|
|
1705
|
+
# **Returns**
|
|
1706
|
+
#
|
|
1707
|
+
# - `Field` — The returned field will be put in the GraphQL response
|
|
1708
|
+
#
|
|
1709
|
+
# :call-seq:
|
|
1710
|
+
# unauthorized_field(GraphQL::UnauthorizedFieldError unauthorized_error) -> Field
|
|
1319
1711
|
def unauthorized_field(unauthorized_error)
|
|
1320
1712
|
unauthorized_object(unauthorized_error)
|
|
1321
1713
|
end
|
|
@@ -1325,11 +1717,23 @@ module GraphQL
|
|
|
1325
1717
|
#
|
|
1326
1718
|
# The default implementation of this method is to follow the GraphQL specification,
|
|
1327
1719
|
# but you can override this to report errors to your bug tracker or customize error handling.
|
|
1328
|
-
#
|
|
1329
|
-
#
|
|
1330
|
-
#
|
|
1331
|
-
#
|
|
1332
|
-
#
|
|
1720
|
+
#
|
|
1721
|
+
# **Parameters**
|
|
1722
|
+
#
|
|
1723
|
+
# - `type_error` (`GraphQL::Error`) — several specific error classes are passed here, see the default implementation for details
|
|
1724
|
+
# - `context` (`GraphQL::Query::Context`) — the context for the currently-running operation
|
|
1725
|
+
#
|
|
1726
|
+
# **Returns**
|
|
1727
|
+
#
|
|
1728
|
+
# - `void`
|
|
1729
|
+
#
|
|
1730
|
+
# **Raises**
|
|
1731
|
+
#
|
|
1732
|
+
# - `GraphQL::ExecutionError` — to return this error to the client
|
|
1733
|
+
# - `GraphQL::Error` — to crash the query and raise a developer-facing error
|
|
1734
|
+
#
|
|
1735
|
+
# :call-seq:
|
|
1736
|
+
# type_error(GraphQL::Error type_error, GraphQL::Query::Context context) -> void | GraphQL::ExecutionError | GraphQL::Error
|
|
1333
1737
|
def type_error(type_error, context)
|
|
1334
1738
|
case type_error
|
|
1335
1739
|
when GraphQL::InvalidNullError
|
|
@@ -1345,12 +1749,21 @@ module GraphQL
|
|
|
1345
1749
|
end
|
|
1346
1750
|
end
|
|
1347
1751
|
|
|
1348
|
-
# A function to call when
|
|
1752
|
+
# A function to call when [.execute](rdoc-ref:.execute) receives an invalid query string
|
|
1349
1753
|
#
|
|
1350
1754
|
# The default is to add the error to `context.errors`
|
|
1351
|
-
#
|
|
1352
|
-
#
|
|
1353
|
-
#
|
|
1755
|
+
#
|
|
1756
|
+
# **Parameters**
|
|
1757
|
+
#
|
|
1758
|
+
# - `parse_err` (`GraphQL::ParseError`) — The error encountered during parsing
|
|
1759
|
+
# - `ctx` (`GraphQL::Query::Context`) — The context for the query where the error occurred
|
|
1760
|
+
#
|
|
1761
|
+
# **Returns**
|
|
1762
|
+
#
|
|
1763
|
+
# - `Object` — void
|
|
1764
|
+
#
|
|
1765
|
+
# :call-seq:
|
|
1766
|
+
# parse_error(GraphQL::ParseError parse_err, GraphQL::Query::Context ctx) -> Object
|
|
1354
1767
|
def parse_error(parse_err, ctx)
|
|
1355
1768
|
ctx.errors.push(parse_err)
|
|
1356
1769
|
end
|
|
@@ -1380,7 +1793,13 @@ module GraphQL
|
|
|
1380
1793
|
end
|
|
1381
1794
|
|
|
1382
1795
|
# Add several directives at once
|
|
1383
|
-
#
|
|
1796
|
+
#
|
|
1797
|
+
# **Parameters**
|
|
1798
|
+
#
|
|
1799
|
+
# - `new_directives` (`Class`)
|
|
1800
|
+
#
|
|
1801
|
+
# :call-seq:
|
|
1802
|
+
# directives(Class *new_directives)
|
|
1384
1803
|
def directives(*new_directives)
|
|
1385
1804
|
if !new_directives.empty?
|
|
1386
1805
|
new_directives.flatten.each { |d| directive(d) }
|
|
@@ -1395,8 +1814,17 @@ module GraphQL
|
|
|
1395
1814
|
end
|
|
1396
1815
|
|
|
1397
1816
|
# Attach a single directive to this schema
|
|
1398
|
-
#
|
|
1399
|
-
#
|
|
1817
|
+
#
|
|
1818
|
+
# **Parameters**
|
|
1819
|
+
#
|
|
1820
|
+
# - `new_directive` (`Class`)
|
|
1821
|
+
#
|
|
1822
|
+
# **Returns**
|
|
1823
|
+
#
|
|
1824
|
+
# - `Object` — void
|
|
1825
|
+
#
|
|
1826
|
+
# :call-seq:
|
|
1827
|
+
# directive(Class new_directive) -> Object
|
|
1400
1828
|
def directive(new_directive)
|
|
1401
1829
|
if use_visibility_profile?
|
|
1402
1830
|
own_directives[new_directive.graphql_name] = new_directive
|
|
@@ -1415,12 +1843,23 @@ module GraphQL
|
|
|
1415
1843
|
}.freeze
|
|
1416
1844
|
end
|
|
1417
1845
|
|
|
1418
|
-
#
|
|
1846
|
+
# **Returns**
|
|
1847
|
+
#
|
|
1848
|
+
# - `GraphQL::Tracing::DetailedTrace` — if it has been configured for this schema
|
|
1419
1849
|
attr_accessor :detailed_trace
|
|
1420
1850
|
|
|
1421
|
-
#
|
|
1422
|
-
#
|
|
1423
|
-
#
|
|
1851
|
+
# [Tracing::DetailedTrace](rdoc-ref:Tracing::DetailedTrace) saves traces when this method returns true.
|
|
1852
|
+
#
|
|
1853
|
+
# **Parameters**
|
|
1854
|
+
#
|
|
1855
|
+
# - `query` (`GraphQL::Query, GraphQL::Execution::Multiplex`) — Called with a multiplex when multiple queries are executed at once (with [.multiplex](rdoc-ref:.multiplex))
|
|
1856
|
+
#
|
|
1857
|
+
# **Returns**
|
|
1858
|
+
#
|
|
1859
|
+
# - `Boolean` — When `true`, save a detailed trace for this query.
|
|
1860
|
+
#
|
|
1861
|
+
# :call-seq:
|
|
1862
|
+
# detailed_trace?(GraphQL::Query | GraphQL::Execution::Multiplex query) -> bool
|
|
1424
1863
|
def detailed_trace?(query)
|
|
1425
1864
|
raise "#{self} must implement `def.detailed_trace?(query)` to use DetailedTrace. Implement this method in your schema definition."
|
|
1426
1865
|
end
|
|
@@ -1458,15 +1897,29 @@ module GraphQL
|
|
|
1458
1897
|
#
|
|
1459
1898
|
# Any custom trace modes _also_ include the default `trace_with ...` modules (that is, those added _without_ any particular `mode: ...` configuration).
|
|
1460
1899
|
#
|
|
1461
|
-
#
|
|
1462
|
-
#
|
|
1463
|
-
#
|
|
1900
|
+
# See [GraphQL::Tracing::Trace](rdoc-ref:GraphQL::Tracing::Trace) for available tracing methods.
|
|
1901
|
+
#
|
|
1902
|
+
# **Examples**
|
|
1903
|
+
#
|
|
1904
|
+
# **Example: Adding a trace in a special mode**
|
|
1905
|
+
#
|
|
1906
|
+
# ```ruby
|
|
1907
|
+
# # only runs when `query.context[:trace_mode]` is `:special`
|
|
1908
|
+
# trace_with SpecialTrace, mode: :special
|
|
1909
|
+
# ```
|
|
1910
|
+
#
|
|
1911
|
+
# **Parameters**
|
|
1464
1912
|
#
|
|
1465
|
-
#
|
|
1466
|
-
#
|
|
1467
|
-
#
|
|
1468
|
-
#
|
|
1469
|
-
#
|
|
1913
|
+
# - `trace_mod` (`Module`) — A module that implements tracing methods
|
|
1914
|
+
# - `mode` (`Symbol`) — Trace module will only be used for this trade mode
|
|
1915
|
+
# - `options` (`Hash`) — Keywords that will be passed to the tracing class during `#initialize`
|
|
1916
|
+
#
|
|
1917
|
+
# **Returns**
|
|
1918
|
+
#
|
|
1919
|
+
# - `void`
|
|
1920
|
+
#
|
|
1921
|
+
# :call-seq:
|
|
1922
|
+
# trace_with(Module trace_mod, Symbol mode:, Hash **options) -> void
|
|
1470
1923
|
def trace_with(trace_mod, mode: :default, **options)
|
|
1471
1924
|
if mode.is_a?(Array)
|
|
1472
1925
|
mode.each { |m| trace_with(trace_mod, mode: m, **options) }
|
|
@@ -1496,7 +1949,13 @@ module GraphQL
|
|
|
1496
1949
|
end
|
|
1497
1950
|
|
|
1498
1951
|
# The options hash for this trace mode
|
|
1499
|
-
#
|
|
1952
|
+
#
|
|
1953
|
+
# **Returns**
|
|
1954
|
+
#
|
|
1955
|
+
# - `Hash`
|
|
1956
|
+
#
|
|
1957
|
+
# :call-seq:
|
|
1958
|
+
# trace_options_for(mode) -> Hash
|
|
1500
1959
|
def trace_options_for(mode)
|
|
1501
1960
|
@trace_options_for_mode ||= {}
|
|
1502
1961
|
@trace_options_for_mode[mode] ||= begin
|
|
@@ -1514,14 +1973,22 @@ module GraphQL
|
|
|
1514
1973
|
|
|
1515
1974
|
# Create a trace instance which will include the trace modules specified for the optional mode.
|
|
1516
1975
|
#
|
|
1517
|
-
# If no `mode:` is given, then
|
|
1976
|
+
# If no `mode:` is given, then [default_trace_mode](rdoc-ref:default_trace_mode) will be used.
|
|
1518
1977
|
#
|
|
1519
|
-
# If this schema is using
|
|
1978
|
+
# If this schema is using [Tracing::DetailedTrace](rdoc-ref:Tracing::DetailedTrace) and [.detailed_trace?](rdoc-ref:.detailed_trace?) returns `true`, then
|
|
1520
1979
|
# DetailedTrace's mode will override the passed-in `mode`.
|
|
1521
1980
|
#
|
|
1522
|
-
#
|
|
1523
|
-
#
|
|
1524
|
-
#
|
|
1981
|
+
# **Parameters**
|
|
1982
|
+
#
|
|
1983
|
+
# - `mode` (`Symbol`) — Trace modules for this trade mode will be included
|
|
1984
|
+
# - `options` (`Hash`) — Keywords that will be passed to the tracing class during `#initialize`
|
|
1985
|
+
#
|
|
1986
|
+
# **Returns**
|
|
1987
|
+
#
|
|
1988
|
+
# - `Tracing::Trace`
|
|
1989
|
+
#
|
|
1990
|
+
# :call-seq:
|
|
1991
|
+
# new_trace(Symbol mode:, Hash **options) -> Tracing::Trace
|
|
1525
1992
|
def new_trace(mode: nil, **options)
|
|
1526
1993
|
should_sample = if detailed_trace
|
|
1527
1994
|
if (query = options[:query])
|
|
@@ -1551,8 +2018,14 @@ module GraphQL
|
|
|
1551
2018
|
trace_class_for_mode.new(**trace_options)
|
|
1552
2019
|
end
|
|
1553
2020
|
|
|
1554
|
-
#
|
|
1555
|
-
#
|
|
2021
|
+
# See [GraphQL::Analysis](rdoc-ref:GraphQL::Analysis) the analysis system
|
|
2022
|
+
#
|
|
2023
|
+
# **Parameters**
|
|
2024
|
+
#
|
|
2025
|
+
# - `new_analyzer` (`Class<GraphQL::Analysis::Analyzer>`) — An analyzer to run on queries to this schema
|
|
2026
|
+
#
|
|
2027
|
+
# :call-seq:
|
|
2028
|
+
# query_analyzer(Class[GraphQL::Analysis::Analyzer] new_analyzer)
|
|
1556
2029
|
def query_analyzer(new_analyzer)
|
|
1557
2030
|
own_query_analyzers << new_analyzer
|
|
1558
2031
|
end
|
|
@@ -1562,8 +2035,14 @@ module GraphQL
|
|
|
1562
2035
|
inherited_qa.empty? ? own_query_analyzers : (inherited_qa + own_query_analyzers)
|
|
1563
2036
|
end
|
|
1564
2037
|
|
|
1565
|
-
#
|
|
1566
|
-
#
|
|
2038
|
+
# See [GraphQL::Analysis](rdoc-ref:GraphQL::Analysis) the analysis system
|
|
2039
|
+
#
|
|
2040
|
+
# **Parameters**
|
|
2041
|
+
#
|
|
2042
|
+
# - `new_analyzer` (`Class<GraphQL::Analysis::Analyzer>`) — An analyzer to run on multiplexes to this schema
|
|
2043
|
+
#
|
|
2044
|
+
# :call-seq:
|
|
2045
|
+
# multiplex_analyzer(Class[GraphQL::Analysis::Analyzer] new_analyzer)
|
|
1567
2046
|
def multiplex_analyzer(new_analyzer)
|
|
1568
2047
|
own_multiplex_analyzers << new_analyzer
|
|
1569
2048
|
end
|
|
@@ -1581,8 +2060,19 @@ module GraphQL
|
|
|
1581
2060
|
end
|
|
1582
2061
|
|
|
1583
2062
|
# Execute a query on itself.
|
|
1584
|
-
#
|
|
1585
|
-
#
|
|
2063
|
+
# See the [GraphQL::Query](rdoc-ref:GraphQL::Query) constructor for arguments.
|
|
2064
|
+
#
|
|
2065
|
+
# `query_str` may be a query string; alternatively pass `document:` with a
|
|
2066
|
+
# parsed document. The common options are `variables:`, `context:`,
|
|
2067
|
+
# `root_value:`, `operation_name:`, `validate:`, `max_depth:`, and
|
|
2068
|
+
# `max_complexity:`. The returned result can be serialized directly as JSON.
|
|
2069
|
+
#
|
|
2070
|
+
# **Returns**
|
|
2071
|
+
#
|
|
2072
|
+
# - `GraphQL::Query::Result` — query result, ready to be serialized as JSON
|
|
2073
|
+
#
|
|
2074
|
+
# :call-seq:
|
|
2075
|
+
# execute(query_str, **kwargs) -> GraphQL::Query::Result
|
|
1586
2076
|
def execute(query_str = nil, **kwargs)
|
|
1587
2077
|
if default_execution_next
|
|
1588
2078
|
execute_next(query_str, **kwargs)
|
|
@@ -1614,24 +2104,42 @@ module GraphQL
|
|
|
1614
2104
|
|
|
1615
2105
|
# Execute several queries on itself, concurrently.
|
|
1616
2106
|
#
|
|
1617
|
-
#
|
|
1618
|
-
#
|
|
1619
|
-
#
|
|
1620
|
-
#
|
|
1621
|
-
#
|
|
1622
|
-
#
|
|
1623
|
-
#
|
|
1624
|
-
#
|
|
1625
|
-
#
|
|
1626
|
-
#
|
|
1627
|
-
#
|
|
1628
|
-
#
|
|
1629
|
-
#
|
|
1630
|
-
#
|
|
1631
|
-
#
|
|
1632
|
-
#
|
|
1633
|
-
#
|
|
1634
|
-
#
|
|
2107
|
+
# See the [GraphQL::Query](rdoc-ref:GraphQL::Query) constructor for query keyword arguments.
|
|
2108
|
+
# Multiplex-level execution is handled by the interpreter's
|
|
2109
|
+
# `GraphQL::Execution::Interpreter.run_all` method.
|
|
2110
|
+
#
|
|
2111
|
+
# **Examples**
|
|
2112
|
+
#
|
|
2113
|
+
# **Example: Run several queries at once**
|
|
2114
|
+
#
|
|
2115
|
+
# ```ruby
|
|
2116
|
+
# context = { ... }
|
|
2117
|
+
# queries = [
|
|
2118
|
+
# { query: params[:query_1], variables: params[:variables_1], context: context },
|
|
2119
|
+
# { query: params[:query_2], variables: params[:variables_2], context: context },
|
|
2120
|
+
# ]
|
|
2121
|
+
# results = MySchema.multiplex(queries)
|
|
2122
|
+
# render json: {
|
|
2123
|
+
# result_1: results[0],
|
|
2124
|
+
# result_2: results[1],
|
|
2125
|
+
# }
|
|
2126
|
+
# ```
|
|
2127
|
+
#
|
|
2128
|
+
# **Parameters**
|
|
2129
|
+
#
|
|
2130
|
+
# - `queries` (`Array<Hash>`) — Keyword arguments for each query
|
|
2131
|
+
#
|
|
2132
|
+
# **Options**
|
|
2133
|
+
#
|
|
2134
|
+
# - `kwargs.:context` (`Hash`) — ({}) Multiplex-level context
|
|
2135
|
+
# - `kwargs.:max_complexity` (`nil, Integer`) — (nil)
|
|
2136
|
+
#
|
|
2137
|
+
# **Returns**
|
|
2138
|
+
#
|
|
2139
|
+
# - `Array<GraphQL::Query::Result>` — One result for each query in the input
|
|
2140
|
+
#
|
|
2141
|
+
# :call-seq:
|
|
2142
|
+
# multiplex(Array[Hash] queries, **kwargs) -> Array[GraphQL::Query::Result]
|
|
1635
2143
|
def multiplex(queries, **kwargs)
|
|
1636
2144
|
if @default_execution_next
|
|
1637
2145
|
multiplex_next(queries, **kwargs)
|
|
@@ -1659,8 +2167,7 @@ module GraphQL
|
|
|
1659
2167
|
end
|
|
1660
2168
|
end
|
|
1661
2169
|
|
|
1662
|
-
#
|
|
1663
|
-
def add_subscription_extension_if_necessary
|
|
2170
|
+
def add_subscription_extension_if_necessary # :nodoc:
|
|
1664
2171
|
# TODO: when there's a proper API for extending root types, migrat this to use it.
|
|
1665
2172
|
if !defined?(@subscription_extension_added) && @subscription_object.is_a?(Class) && self.subscriptions
|
|
1666
2173
|
@subscription_extension_added = true
|
|
@@ -1674,9 +2181,18 @@ module GraphQL
|
|
|
1674
2181
|
|
|
1675
2182
|
# Called when execution encounters a `SystemStackError`. By default, it adds a client-facing error to the response.
|
|
1676
2183
|
# You could modify this method to report this error to your bug tracker.
|
|
1677
|
-
#
|
|
1678
|
-
#
|
|
1679
|
-
#
|
|
2184
|
+
#
|
|
2185
|
+
# **Parameters**
|
|
2186
|
+
#
|
|
2187
|
+
# - `query` (`GraphQL::Query`)
|
|
2188
|
+
# - `err` (`SystemStackError`)
|
|
2189
|
+
#
|
|
2190
|
+
# **Returns**
|
|
2191
|
+
#
|
|
2192
|
+
# - `void`
|
|
2193
|
+
#
|
|
2194
|
+
# :call-seq:
|
|
2195
|
+
# query_stack_error(GraphQL::Query query, SystemStackError err) -> void
|
|
1680
2196
|
def query_stack_error(query, err)
|
|
1681
2197
|
query.context.errors.push(GraphQL::ExecutionError.new("This query is too large to execute."))
|
|
1682
2198
|
end
|
|
@@ -1684,8 +2200,7 @@ module GraphQL
|
|
|
1684
2200
|
# Call the given block at the right time, either:
|
|
1685
2201
|
# - Right away, if `value` is not registered with `lazy_resolve`
|
|
1686
2202
|
# - After resolving `value`, if it's registered with `lazy_resolve` (eg, `Promise`)
|
|
1687
|
-
#
|
|
1688
|
-
def after_lazy(value, &block)
|
|
2203
|
+
def after_lazy(value, &block) # :nodoc:
|
|
1689
2204
|
if lazy?(value)
|
|
1690
2205
|
GraphQL::Execution::Lazy.new do
|
|
1691
2206
|
result = sync_lazy(value)
|
|
@@ -1698,10 +2213,15 @@ module GraphQL
|
|
|
1698
2213
|
end
|
|
1699
2214
|
|
|
1700
2215
|
# Override this method to handle lazy objects in a custom way.
|
|
1701
|
-
#
|
|
1702
|
-
#
|
|
1703
|
-
#
|
|
1704
|
-
|
|
2216
|
+
#
|
|
2217
|
+
# **Parameters**
|
|
2218
|
+
#
|
|
2219
|
+
# - `value` (`Object`) — an instance of a class registered with [.lazy_resolve](rdoc-ref:.lazy_resolve)
|
|
2220
|
+
#
|
|
2221
|
+
# **Returns**
|
|
2222
|
+
#
|
|
2223
|
+
# - `Object` — A GraphQL-ready (non-lazy) object
|
|
2224
|
+
def sync_lazy(value) # :nodoc:
|
|
1705
2225
|
lazy_method = lazy_method_name(value)
|
|
1706
2226
|
if lazy_method
|
|
1707
2227
|
synced_value = value.public_send(lazy_method)
|
|
@@ -1711,21 +2231,33 @@ module GraphQL
|
|
|
1711
2231
|
end
|
|
1712
2232
|
end
|
|
1713
2233
|
|
|
1714
|
-
#
|
|
2234
|
+
# **Returns**
|
|
2235
|
+
#
|
|
2236
|
+
# - `Symbol, nil` — The method name to lazily resolve `obj`, or nil if `obj`'s class wasn't registered with [.lazy_resolve](rdoc-ref:.lazy_resolve).
|
|
2237
|
+
#
|
|
2238
|
+
# :call-seq:
|
|
2239
|
+
# lazy_method_name(obj) -> Symbol | nil
|
|
1715
2240
|
def lazy_method_name(obj)
|
|
1716
2241
|
lazy_methods.get(obj)
|
|
1717
2242
|
end
|
|
1718
2243
|
|
|
1719
|
-
#
|
|
2244
|
+
# **Returns**
|
|
2245
|
+
#
|
|
2246
|
+
# - `Boolean` — True if this object should be lazily resolved
|
|
2247
|
+
#
|
|
2248
|
+
# :call-seq:
|
|
2249
|
+
# lazy?(obj) -> bool
|
|
1720
2250
|
def lazy?(obj)
|
|
1721
2251
|
!!lazy_method_name(obj)
|
|
1722
2252
|
end
|
|
1723
2253
|
|
|
1724
2254
|
# Return a lazy if any of `maybe_lazies` are lazy,
|
|
1725
2255
|
# otherwise, call the block eagerly and return the result.
|
|
1726
|
-
#
|
|
1727
|
-
#
|
|
1728
|
-
|
|
2256
|
+
#
|
|
2257
|
+
# **Parameters**
|
|
2258
|
+
#
|
|
2259
|
+
# - `maybe_lazies` (`Array`)
|
|
2260
|
+
def after_any_lazies(maybe_lazies) # :nodoc:
|
|
1729
2261
|
if maybe_lazies.any? { |l| lazy?(l) }
|
|
1730
2262
|
GraphQL::Execution::Lazy.all(maybe_lazies).then do |result|
|
|
1731
2263
|
yield result
|
|
@@ -1757,10 +2289,19 @@ module GraphQL
|
|
|
1757
2289
|
# If you need to support previous, non-spec behavior which allowed selecting union fields
|
|
1758
2290
|
# but *not* selecting any fields on that union, set this to `true` to continue allowing that behavior.
|
|
1759
2291
|
#
|
|
1760
|
-
# If this is `true`, then
|
|
2292
|
+
# If this is `true`, then [.legacy_invalid_empty_selections_on_union_with_type](rdoc-ref:.legacy_invalid_empty_selections_on_union_with_type) will be called with [Query](rdoc-ref:Query) objects
|
|
1761
2293
|
# with that kind of selections. You must implement that method
|
|
1762
|
-
#
|
|
1763
|
-
#
|
|
2294
|
+
#
|
|
2295
|
+
# **Parameters**
|
|
2296
|
+
#
|
|
2297
|
+
# - `new_value` (`Boolean`)
|
|
2298
|
+
#
|
|
2299
|
+
# **Returns**
|
|
2300
|
+
#
|
|
2301
|
+
# - `true, false, nil`
|
|
2302
|
+
#
|
|
2303
|
+
# :call-seq:
|
|
2304
|
+
# allow_legacy_invalid_empty_selections_on_union(bool new_value) -> true | false | nil
|
|
1764
2305
|
def allow_legacy_invalid_empty_selections_on_union(new_value = NOT_CONFIGURED)
|
|
1765
2306
|
if NOT_CONFIGURED.equal?(new_value)
|
|
1766
2307
|
if defined?(@allow_legacy_invalid_empty_selections_on_union)
|
|
@@ -1781,10 +2322,19 @@ module GraphQL
|
|
|
1781
2322
|
# You should implement this method or `legacy_invalid_empty_selections_on_union_with_type`
|
|
1782
2323
|
# to log the violation so that you can contact clients and notify them about changing their queries.
|
|
1783
2324
|
# Then return a suitable value to tell GraphQL-Ruby how to continue.
|
|
1784
|
-
#
|
|
1785
|
-
#
|
|
1786
|
-
#
|
|
1787
|
-
#
|
|
2325
|
+
#
|
|
2326
|
+
# **Parameters**
|
|
2327
|
+
#
|
|
2328
|
+
# - `query` (`GraphQL::Query`)
|
|
2329
|
+
#
|
|
2330
|
+
# **Returns**
|
|
2331
|
+
#
|
|
2332
|
+
# - `:return_validation_error` — Let GraphQL-Ruby return the (new) normal validation error for this query
|
|
2333
|
+
# - `String` — A validation error to return for this query
|
|
2334
|
+
# - `nil` — Don't send the client an error, continue the legacy behavior (allow this query to execute)
|
|
2335
|
+
#
|
|
2336
|
+
# :call-seq:
|
|
2337
|
+
# legacy_invalid_empty_selections_on_union(GraphQL::Query query) -> :return_validation_error | String | nil
|
|
1788
2338
|
def legacy_invalid_empty_selections_on_union(query)
|
|
1789
2339
|
raise "Implement `def self.legacy_invalid_empty_selections_on_union_with_type(query, type)` or `def self.legacy_invalid_empty_selections_on_union(query)` to handle this scenario"
|
|
1790
2340
|
end
|
|
@@ -1795,24 +2345,101 @@ module GraphQL
|
|
|
1795
2345
|
# You should implement this method to log the violation so that you can contact clients
|
|
1796
2346
|
# and notify them about changing their queries. Then return a suitable value to
|
|
1797
2347
|
# tell GraphQL-Ruby how to continue.
|
|
1798
|
-
#
|
|
1799
|
-
#
|
|
1800
|
-
#
|
|
1801
|
-
#
|
|
1802
|
-
#
|
|
2348
|
+
#
|
|
2349
|
+
# **Parameters**
|
|
2350
|
+
#
|
|
2351
|
+
# - `query` (`GraphQL::Query`)
|
|
2352
|
+
# - `type` (`Module`) — A GraphQL type definition
|
|
2353
|
+
#
|
|
2354
|
+
# **Returns**
|
|
2355
|
+
#
|
|
2356
|
+
# - `:return_validation_error` — Let GraphQL-Ruby return the (new) normal validation error for this query
|
|
2357
|
+
# - `String` — A validation error to return for this query
|
|
2358
|
+
# - `nil` — Don't send the client an error, continue the legacy behavior (allow this query to execute)
|
|
2359
|
+
#
|
|
2360
|
+
# :call-seq:
|
|
2361
|
+
# legacy_invalid_empty_selections_on_union_with_type(GraphQL::Query query, Module type) -> :return_validation_error | String | nil
|
|
1803
2362
|
def legacy_invalid_empty_selections_on_union_with_type(query, type)
|
|
1804
2363
|
legacy_invalid_empty_selections_on_union(query)
|
|
1805
2364
|
end
|
|
1806
2365
|
|
|
2366
|
+
# This setting controls how GraphQL-Ruby handles variable usages which the GraphQL spec doesn't allow,
|
|
2367
|
+
# but which previous versions of GraphQL-Ruby didn't reject:
|
|
2368
|
+
#
|
|
2369
|
+
# - A variable in a fragment, when the fragment comes before the operation, or when another operation uses the fragment
|
|
2370
|
+
# - A nullable variable with a `= null` default value, in a non-null position
|
|
2371
|
+
# - A variable in a nested list value, for example `[[$var]]`
|
|
2372
|
+
#
|
|
2373
|
+
# When set to `false`, GraphQL-Ruby will reject those queries with a validation error (as per the GraphQL spec).
|
|
2374
|
+
#
|
|
2375
|
+
# When set to `true`, GraphQL-Ruby will call [.legacy_invalid_variable_usages](rdoc-ref:.legacy_invalid_variable_usages) when the scenario is encountered.
|
|
2376
|
+
#
|
|
2377
|
+
# When not configured, GraphQL-Ruby allows those queries and logs a warning.
|
|
2378
|
+
#
|
|
2379
|
+
# **Parameters**
|
|
2380
|
+
#
|
|
2381
|
+
# - `new_value` (`Boolean`) — `true` permits the legacy behavior, `false` rejects it.
|
|
2382
|
+
#
|
|
2383
|
+
# **Returns**
|
|
2384
|
+
#
|
|
2385
|
+
# - `true, false, nil`
|
|
2386
|
+
#
|
|
2387
|
+
# :call-seq:
|
|
2388
|
+
# allow_legacy_invalid_variable_usages(bool new_value) -> true | false | nil
|
|
2389
|
+
def allow_legacy_invalid_variable_usages(new_value = NOT_CONFIGURED)
|
|
2390
|
+
if NOT_CONFIGURED.equal?(new_value)
|
|
2391
|
+
if defined?(@allow_legacy_invalid_variable_usages)
|
|
2392
|
+
@allow_legacy_invalid_variable_usages
|
|
2393
|
+
else
|
|
2394
|
+
find_inherited_value(:allow_legacy_invalid_variable_usages)
|
|
2395
|
+
end
|
|
2396
|
+
else
|
|
2397
|
+
@allow_legacy_invalid_variable_usages = new_value
|
|
2398
|
+
end
|
|
2399
|
+
end
|
|
2400
|
+
|
|
2401
|
+
# This method is called when the query uses a variable in a way which the GraphQL spec doesn't allow,
|
|
2402
|
+
# but which previous versions of GraphQL-Ruby allowed. See [.allow_legacy_invalid_variable_usages](rdoc-ref:.allow_legacy_invalid_variable_usages).
|
|
2403
|
+
#
|
|
2404
|
+
# You should implement this method to log the violation so that you can contact clients
|
|
2405
|
+
# and notify them about changing their queries. Then return a suitable value to
|
|
2406
|
+
# tell GraphQL-Ruby how to continue.
|
|
2407
|
+
#
|
|
2408
|
+
# **Parameters**
|
|
2409
|
+
#
|
|
2410
|
+
# - `query` (`GraphQL::Query`)
|
|
2411
|
+
# - `variable_definition` (`GraphQL::Language::Nodes::VariableDefinition`) — The definition of the variable
|
|
2412
|
+
# - `argument` (`GraphQL::Language::Nodes::Argument`) — The argument which uses the variable. You might call `.line` and `.col` for custom error reporting.
|
|
2413
|
+
#
|
|
2414
|
+
# **Returns**
|
|
2415
|
+
#
|
|
2416
|
+
# - `:return_validation_error` — Let GraphQL-Ruby return the (new) normal validation error for this query
|
|
2417
|
+
# - `String` — A validation error to return for this query
|
|
2418
|
+
# - `nil` — Don't send the client an error, continue the legacy behavior (allow this query to execute)
|
|
2419
|
+
#
|
|
2420
|
+
# :call-seq:
|
|
2421
|
+
# legacy_invalid_variable_usages(GraphQL::Query query, GraphQL::Language::Nodes::VariableDefinition variable_definition, GraphQL::Language::Nodes::Argument argument) -> :return_validation_error | String | nil
|
|
2422
|
+
def legacy_invalid_variable_usages(query, variable_definition, argument)
|
|
2423
|
+
raise "Implement #{self}.legacy_invalid_variable_usages to handle this invalid variable usage"
|
|
2424
|
+
end
|
|
2425
|
+
|
|
1807
2426
|
# This setting controls how GraphQL-Ruby handles overlapping selections on scalar types when the types
|
|
1808
2427
|
# don't match.
|
|
1809
2428
|
#
|
|
1810
2429
|
# When set to `false`, GraphQL-Ruby will reject those queries with a validation error (as per the GraphQL spec).
|
|
1811
2430
|
#
|
|
1812
|
-
# When set to `true`, GraphQL-Ruby will call
|
|
2431
|
+
# When set to `true`, GraphQL-Ruby will call [.legacy_invalid_return_type_conflicts](rdoc-ref:.legacy_invalid_return_type_conflicts) when the scenario is encountered.
|
|
1813
2432
|
#
|
|
1814
|
-
#
|
|
1815
|
-
#
|
|
2433
|
+
# **Parameters**
|
|
2434
|
+
#
|
|
2435
|
+
# - `new_value` (`Boolean`) — `true` permits the legacy behavior, `false` rejects it.
|
|
2436
|
+
#
|
|
2437
|
+
# **Returns**
|
|
2438
|
+
#
|
|
2439
|
+
# - `true, false, nil`
|
|
2440
|
+
#
|
|
2441
|
+
# :call-seq:
|
|
2442
|
+
# allow_legacy_invalid_return_type_conflicts(bool new_value) -> true | false | nil
|
|
1816
2443
|
def allow_legacy_invalid_return_type_conflicts(new_value = NOT_CONFIGURED)
|
|
1817
2444
|
if NOT_CONFIGURED.equal?(new_value)
|
|
1818
2445
|
if defined?(@allow_legacy_invalid_return_type_conflicts)
|
|
@@ -1833,38 +2460,117 @@ module GraphQL
|
|
|
1833
2460
|
# (Changing the field return type would be a breaking change, but if it works for your client use cases,
|
|
1834
2461
|
# that might work, too.)
|
|
1835
2462
|
#
|
|
1836
|
-
#
|
|
1837
|
-
#
|
|
1838
|
-
#
|
|
1839
|
-
#
|
|
1840
|
-
#
|
|
1841
|
-
#
|
|
1842
|
-
#
|
|
1843
|
-
#
|
|
2463
|
+
# **Parameters**
|
|
2464
|
+
#
|
|
2465
|
+
# - `query` (`GraphQL::Query`)
|
|
2466
|
+
# - `type1` (`Module`) — A GraphQL type definition
|
|
2467
|
+
# - `type2` (`Module`) — A GraphQL type definition
|
|
2468
|
+
# - `node1` (`GraphQL::Language::Nodes::Field`) — This node is recognized as conflicting. You might call `.line` and `.col` for custom error reporting.
|
|
2469
|
+
# - `node2` (`GraphQL::Language::Nodes::Field`) — The other node recognized as conflicting.
|
|
2470
|
+
#
|
|
2471
|
+
# **Returns**
|
|
2472
|
+
#
|
|
2473
|
+
# - `:return_validation_error` — Let GraphQL-Ruby return the (new) normal validation error for this query
|
|
2474
|
+
# - `String` — A validation error to return for this query
|
|
2475
|
+
# - `nil` — Don't send the client an error, continue the legacy behavior (allow this query to execute)
|
|
2476
|
+
#
|
|
2477
|
+
# :call-seq:
|
|
2478
|
+
# legacy_invalid_return_type_conflicts(GraphQL::Query query, Module type1, Module type2, GraphQL::Language::Nodes::Field node1, GraphQL::Language::Nodes::Field node2) -> :return_validation_error | String | nil
|
|
1844
2479
|
def legacy_invalid_return_type_conflicts(query, type1, type2, node1, node2)
|
|
1845
2480
|
raise "Implement #{self}.legacy_invalid_return_type_conflicts to handle this invalid selection"
|
|
1846
2481
|
end
|
|
1847
2482
|
|
|
2483
|
+
# This setting controls how GraphQL-Ruby handles fields with the same response name but different names or arguments,
|
|
2484
|
+
# when previous versions of GraphQL-Ruby treated them as mutually exclusive, but the GraphQL spec doesn't.
|
|
2485
|
+
# The spec treats fields as mutually exclusive only when their parent types are different object types. For example:
|
|
2486
|
+
#
|
|
2487
|
+
# - `... on Product { ...ProductFields options(first: 2) { id } }`, when `ProductFields` also selects `options` on `Product`
|
|
2488
|
+
# - `... on Feline { volume: meowVolume }` and `... on Canine { volume: barkVolume }`, when `Feline` and `Canine` are interfaces
|
|
2489
|
+
#
|
|
2490
|
+
# When set to `false`, GraphQL-Ruby will reject those queries with a validation error (as per the GraphQL spec).
|
|
2491
|
+
#
|
|
2492
|
+
# When set to `true`, GraphQL-Ruby will call [.legacy_invalid_field_conflicts](rdoc-ref:.legacy_invalid_field_conflicts) when the scenario is encountered.
|
|
2493
|
+
#
|
|
2494
|
+
# When not configured, GraphQL-Ruby allows those queries and logs a warning.
|
|
2495
|
+
#
|
|
2496
|
+
# **Parameters**
|
|
2497
|
+
#
|
|
2498
|
+
# - `new_value` (`Boolean`) — `true` permits the legacy behavior, `false` rejects it.
|
|
2499
|
+
#
|
|
2500
|
+
# **Returns**
|
|
2501
|
+
#
|
|
2502
|
+
# - `true, false, nil`
|
|
2503
|
+
#
|
|
2504
|
+
# :call-seq:
|
|
2505
|
+
# allow_legacy_invalid_field_conflicts(bool new_value) -> true | false | nil
|
|
2506
|
+
def allow_legacy_invalid_field_conflicts(new_value = NOT_CONFIGURED)
|
|
2507
|
+
if NOT_CONFIGURED.equal?(new_value)
|
|
2508
|
+
if defined?(@allow_legacy_invalid_field_conflicts)
|
|
2509
|
+
@allow_legacy_invalid_field_conflicts
|
|
2510
|
+
else
|
|
2511
|
+
find_inherited_value(:allow_legacy_invalid_field_conflicts)
|
|
2512
|
+
end
|
|
2513
|
+
else
|
|
2514
|
+
@allow_legacy_invalid_field_conflicts = new_value
|
|
2515
|
+
end
|
|
2516
|
+
end
|
|
2517
|
+
|
|
2518
|
+
# This method is called when the query has two fields with the same response name but different names or arguments,
|
|
2519
|
+
# which previous versions of GraphQL-Ruby allowed. See [.allow_legacy_invalid_field_conflicts](rdoc-ref:.allow_legacy_invalid_field_conflicts).
|
|
2520
|
+
#
|
|
2521
|
+
# You should implement this method to log the violation so that you can contact clients
|
|
2522
|
+
# and notify them about changing their queries. Then return a suitable value to
|
|
2523
|
+
# tell GraphQL-Ruby how to continue.
|
|
2524
|
+
#
|
|
2525
|
+
# **Parameters**
|
|
2526
|
+
#
|
|
2527
|
+
# - `query` (`GraphQL::Query`)
|
|
2528
|
+
# - `node1` (`GraphQL::Language::Nodes::Field`) — This node is recognized as conflicting. You might call `.line` and `.col` for custom error reporting.
|
|
2529
|
+
# - `node2` (`GraphQL::Language::Nodes::Field`) — The other node recognized as conflicting.
|
|
2530
|
+
#
|
|
2531
|
+
# **Returns**
|
|
2532
|
+
#
|
|
2533
|
+
# - `:return_validation_error` — Let GraphQL-Ruby return the (new) normal validation error for this query
|
|
2534
|
+
# - `String` — A validation error to return for this query
|
|
2535
|
+
# - `nil` — Don't send the client an error, continue the legacy behavior (allow this query to execute)
|
|
2536
|
+
#
|
|
2537
|
+
# :call-seq:
|
|
2538
|
+
# legacy_invalid_field_conflicts(GraphQL::Query query, GraphQL::Language::Nodes::Field node1, GraphQL::Language::Nodes::Field node2) -> :return_validation_error | String | nil
|
|
2539
|
+
def legacy_invalid_field_conflicts(query, node1, node2)
|
|
2540
|
+
raise "Implement #{self}.legacy_invalid_field_conflicts to handle this invalid selection"
|
|
2541
|
+
end
|
|
2542
|
+
|
|
1848
2543
|
# The legacy complexity implementation included several bugs:
|
|
1849
2544
|
#
|
|
1850
2545
|
# - In some cases, it used the lexically _last_ field to determine a cost, instead of calculating the maximum among selections
|
|
1851
2546
|
# - In some cases, it called field complexity hooks repeatedly (when it should have only called them once)
|
|
1852
2547
|
#
|
|
1853
2548
|
# The future implementation may produce higher total complexity scores, so it's not active by default yet. You can opt into
|
|
1854
|
-
# the future default behavior by configuring `:future` here. Or, you can choose a mode for each query with
|
|
2549
|
+
# the future default behavior by configuring `:future` here. Or, you can choose a mode for each query with [.complexity_cost_calculation_mode_for](rdoc-ref:.complexity_cost_calculation_mode_for).
|
|
1855
2550
|
#
|
|
1856
2551
|
# The legacy mode is currently maintained alongside the future one, but it will be removed in a future GraphQL-Ruby version.
|
|
1857
2552
|
#
|
|
1858
|
-
# If you choose `:compare`, you must also implement
|
|
2553
|
+
# If you choose `:compare`, you must also implement [.legacy_complexity_cost_calculation_mismatch](rdoc-ref:.legacy_complexity_cost_calculation_mismatch) to handle the input somehow.
|
|
2554
|
+
#
|
|
2555
|
+
# **Examples**
|
|
2556
|
+
#
|
|
2557
|
+
# **Example: Opting into the future calculation mode**
|
|
1859
2558
|
#
|
|
1860
|
-
#
|
|
1861
|
-
#
|
|
2559
|
+
# ```ruby
|
|
2560
|
+
# complexity_cost_calculation_mode(:future)
|
|
2561
|
+
# ```
|
|
1862
2562
|
#
|
|
1863
|
-
#
|
|
1864
|
-
# complexity_cost_calculation_mode(:legacy)
|
|
2563
|
+
# **Example: Choosing the legacy mode (which will work until that mode is removed...)**
|
|
1865
2564
|
#
|
|
1866
|
-
#
|
|
1867
|
-
#
|
|
2565
|
+
# ```ruby
|
|
2566
|
+
# complexity_cost_calculation_mode(:legacy)
|
|
2567
|
+
# ```
|
|
2568
|
+
#
|
|
2569
|
+
# **Example: Run both modes for every query, call [.legacy_complexity_cost_calculation_mismatch](rdoc-ref:.legacy_complexity_cost_calculation_mismatch) when they don't match:**
|
|
2570
|
+
#
|
|
2571
|
+
# ```ruby
|
|
2572
|
+
# complexity_cost_calculation_mode(:compare)
|
|
2573
|
+
# ```
|
|
1868
2574
|
def complexity_cost_calculation_mode(new_mode = NOT_CONFIGURED)
|
|
1869
2575
|
if NOT_CONFIGURED.equal?(new_mode)
|
|
1870
2576
|
if defined?(@complexity_cost_calculation_mode)
|
|
@@ -1882,50 +2588,81 @@ module GraphQL
|
|
|
1882
2588
|
# This is a way to check the compatibility of queries coming to your API without adding overhead of running `:compare`
|
|
1883
2589
|
# for every query. You could sample traffic, turn it off/on with feature flags, or anything else.
|
|
1884
2590
|
#
|
|
1885
|
-
#
|
|
1886
|
-
#
|
|
1887
|
-
#
|
|
1888
|
-
#
|
|
1889
|
-
#
|
|
1890
|
-
#
|
|
1891
|
-
#
|
|
2591
|
+
# **Examples**
|
|
2592
|
+
#
|
|
2593
|
+
# **Example: Sampling traffic**
|
|
2594
|
+
#
|
|
2595
|
+
# ```ruby
|
|
2596
|
+
# def self.complexity_cost_calculation_mode_for(_context)
|
|
2597
|
+
# if rand < 0.1 # 10% of the time
|
|
2598
|
+
# :compare
|
|
2599
|
+
# else
|
|
2600
|
+
# :legacy
|
|
1892
2601
|
# end
|
|
2602
|
+
# end
|
|
2603
|
+
# ```
|
|
2604
|
+
#
|
|
2605
|
+
# **Example: Using a feature flag to manage future mode**
|
|
1893
2606
|
#
|
|
1894
|
-
#
|
|
1895
|
-
#
|
|
1896
|
-
#
|
|
1897
|
-
#
|
|
1898
|
-
#
|
|
1899
|
-
#
|
|
1900
|
-
#
|
|
1901
|
-
#
|
|
1902
|
-
#
|
|
1903
|
-
# end
|
|
2607
|
+
# ```ruby
|
|
2608
|
+
# def complexity_cost_calculation_mode_for(context)
|
|
2609
|
+
# current_user = context[:current_user]
|
|
2610
|
+
# if Flipper.enabled?(:future_complexity_cost, current_user)
|
|
2611
|
+
# :future
|
|
2612
|
+
# elsif rand < 0.5 # 50%
|
|
2613
|
+
# :compare
|
|
2614
|
+
# else
|
|
2615
|
+
# :legacy
|
|
1904
2616
|
# end
|
|
2617
|
+
# end
|
|
2618
|
+
# ```
|
|
2619
|
+
#
|
|
2620
|
+
# **Parameters**
|
|
1905
2621
|
#
|
|
1906
|
-
#
|
|
1907
|
-
#
|
|
1908
|
-
#
|
|
1909
|
-
#
|
|
2622
|
+
# - `multiplex_context` (`Hash`) — The context for the currently-running `Execution::Multiplex` (which contains one or more queries)
|
|
2623
|
+
#
|
|
2624
|
+
# **Returns**
|
|
2625
|
+
#
|
|
2626
|
+
# - `:future` — Use the new calculation algorithm -- may be higher than `:legacy`
|
|
2627
|
+
# - `:legacy` — Use the legacy calculation algorithm, warts and all
|
|
2628
|
+
# - `:compare` — Run both algorithms and call [.legacy_complexity_cost_calculation_mismatch](rdoc-ref:.legacy_complexity_cost_calculation_mismatch) if they don't match
|
|
2629
|
+
#
|
|
2630
|
+
# :call-seq:
|
|
2631
|
+
# complexity_cost_calculation_mode_for(Hash multiplex_context) -> :future | :legacy | :compare
|
|
1910
2632
|
def complexity_cost_calculation_mode_for(multiplex_context)
|
|
1911
2633
|
complexity_cost_calculation_mode
|
|
1912
2634
|
end
|
|
1913
2635
|
|
|
1914
2636
|
# Implement this method in your schema to handle mismatches when `:compare` is used.
|
|
1915
2637
|
#
|
|
1916
|
-
#
|
|
1917
|
-
#
|
|
1918
|
-
#
|
|
1919
|
-
#
|
|
1920
|
-
#
|
|
1921
|
-
#
|
|
1922
|
-
#
|
|
1923
|
-
#
|
|
1924
|
-
#
|
|
1925
|
-
#
|
|
1926
|
-
#
|
|
1927
|
-
#
|
|
1928
|
-
#
|
|
2638
|
+
# See [Query::Context#add_error](rdoc-ref:Query::Context#add_error) Adding an error to the response to notify the client
|
|
2639
|
+
# See [Query::Context#response_extensions](rdoc-ref:Query::Context#response_extensions) Adding key-value pairs to the response `"extensions" => { ... }`
|
|
2640
|
+
#
|
|
2641
|
+
# **Examples**
|
|
2642
|
+
#
|
|
2643
|
+
# **Example: Logging the mismatch**
|
|
2644
|
+
#
|
|
2645
|
+
# ```ruby
|
|
2646
|
+
# def self.legacy_cost_calculation_mismatch(multiplex, future_cost, legacy_cost)
|
|
2647
|
+
# client_id = multiplex.context[:api_client].id
|
|
2648
|
+
# operation_names = multiplex.queries.map { |q| q.selected_operation_name || "anonymous" }.join(", ")
|
|
2649
|
+
# Stats.increment(:complexity_mismatch, tags: { client: client_id, ops: operation_names })
|
|
2650
|
+
# legacy_cost
|
|
2651
|
+
# end
|
|
2652
|
+
# ```
|
|
2653
|
+
#
|
|
2654
|
+
# **Parameters**
|
|
2655
|
+
#
|
|
2656
|
+
# - `multiplex` (`GraphQL::Execution::Multiplex`)
|
|
2657
|
+
# - `future_complexity_cost` (`Integer`)
|
|
2658
|
+
# - `legacy_complexity_cost` (`Integer`)
|
|
2659
|
+
#
|
|
2660
|
+
# **Returns**
|
|
2661
|
+
#
|
|
2662
|
+
# - `Integer` — the cost to use for this query (probably one of `future_complexity_cost` or `legacy_complexity_cost`)
|
|
2663
|
+
#
|
|
2664
|
+
# :call-seq:
|
|
2665
|
+
# legacy_complexity_cost_calculation_mismatch(GraphQL::Execution::Multiplex multiplex, Integer future_complexity_cost, Integer legacy_complexity_cost) -> Integer
|
|
1929
2666
|
def legacy_complexity_cost_calculation_mismatch(multiplex, future_complexity_cost, legacy_complexity_cost)
|
|
1930
2667
|
raise "Implement #{self}.legacy_complexity_cost(multiplex, future_complexity_cost, legacy_complexity_cost) to handle this mismatch (#{future_complexity_cost} vs. #{legacy_complexity_cost}) and return a value to use"
|
|
1931
2668
|
end
|
|
@@ -1947,8 +2684,16 @@ module GraphQL
|
|
|
1947
2684
|
nil
|
|
1948
2685
|
end
|
|
1949
2686
|
|
|
1950
|
-
#
|
|
1951
|
-
#
|
|
2687
|
+
# **Parameters**
|
|
2688
|
+
#
|
|
2689
|
+
# - `t` (`Module, Array<Module>`)
|
|
2690
|
+
#
|
|
2691
|
+
# **Returns**
|
|
2692
|
+
#
|
|
2693
|
+
# - `void`
|
|
2694
|
+
#
|
|
2695
|
+
# :call-seq:
|
|
2696
|
+
# add_type_and_traverse(Module | Array[Module] t, root:) -> void
|
|
1952
2697
|
def add_type_and_traverse(t, root:)
|
|
1953
2698
|
if root
|
|
1954
2699
|
@root_types ||= []
|
|
@@ -2069,6 +2814,8 @@ module GraphQL
|
|
|
2069
2814
|
end
|
|
2070
2815
|
end
|
|
2071
2816
|
|
|
2817
|
+
#--
|
|
2818
|
+
# @requires_ancestor: singleton(GraphQL::Schema)
|
|
2072
2819
|
module SubclassGetReferencesTo
|
|
2073
2820
|
def get_references_to(type_defn)
|
|
2074
2821
|
own_refs = own_references_to[type_defn]
|
|
@@ -2088,8 +2835,7 @@ module GraphQL
|
|
|
2088
2835
|
# Install these here so that subclasses will also install it.
|
|
2089
2836
|
self.connections = GraphQL::Pagination::Connections.new(schema: self)
|
|
2090
2837
|
|
|
2091
|
-
#
|
|
2092
|
-
module DefaultTraceClass
|
|
2838
|
+
module DefaultTraceClass # :nodoc:
|
|
2093
2839
|
end
|
|
2094
2840
|
end
|
|
2095
2841
|
end
|