graphql 2.6.12 → 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 +8 -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 +91 -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 +22 -6
- 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 +66 -23
- 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 +17 -11
- 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 +118 -21
- 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 +4 -1
- 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 +20 -17
- 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 +48 -8
- 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 +4 -1
- 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
|
@@ -1,27 +1,79 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
# typed: true
|
|
2
3
|
module GraphQL
|
|
3
4
|
module StaticValidation
|
|
5
|
+
#--
|
|
6
|
+
# @requires_ancestor: GraphQL::StaticValidation::BaseVisitor
|
|
4
7
|
module VariableUsagesAreAllowed
|
|
8
|
+
# A variable in a fragment. It's checked after the visit, against each operation which uses the fragment.
|
|
9
|
+
# `list_depth` is the number of list literals around the variable.
|
|
10
|
+
FragmentVariableUsage = Struct.new(:argument_owner, :arg_node, :variable_name, :list_depth, :path, :checked_variable_types)
|
|
11
|
+
|
|
5
12
|
def initialize(*)
|
|
6
13
|
super
|
|
7
14
|
# holds { name => ast_node } pairs
|
|
8
15
|
@declared_variables = {}
|
|
16
|
+
@operation_declared_variables = {}.compare_by_identity #: Hash[GraphQL::Language::Nodes::OperationDefinition, Hash[String, GraphQL::Language::Nodes::VariableDefinition]]
|
|
17
|
+
@variable_usages_fragment_definition = nil
|
|
18
|
+
@fragment_variable_usages = nil #: Hash[GraphQL::Language::Nodes::FragmentDefinition, Array[FragmentVariableUsage]]?
|
|
19
|
+
@reported_fragment_variable_errors = nil #: Hash[GraphQL::Language::Nodes::Argument, Hash[String, bool]]?
|
|
20
|
+
@allow_legacy_invalid_variable_usages = @schema.allow_legacy_invalid_variable_usages
|
|
21
|
+
# The arguments and variables which have an error from the legacy check
|
|
22
|
+
@legacy_errors = nil #: Hash[GraphQL::Language::Nodes::Argument, Hash[String, bool]]?
|
|
9
23
|
end
|
|
10
24
|
|
|
11
25
|
def on_operation_definition(node, parent)
|
|
12
26
|
@declared_variables = node.variables.each_with_object({}) { |var, memo| memo[var.name] = var }
|
|
27
|
+
@operation_declared_variables[node] = @declared_variables
|
|
13
28
|
super
|
|
14
29
|
end
|
|
15
30
|
|
|
16
|
-
def
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
31
|
+
def on_fragment_definition(node, parent)
|
|
32
|
+
@variable_usages_fragment_definition = node
|
|
33
|
+
super
|
|
34
|
+
@variable_usages_fragment_definition = nil
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def on_document(node, parent)
|
|
38
|
+
super
|
|
39
|
+
# A fragment can come before the operations which use it, and many operations can use it.
|
|
40
|
+
# So, check its variable usages after the visit, against each operation which uses it.
|
|
41
|
+
fragment_usages = @fragment_variable_usages
|
|
42
|
+
return if fragment_usages.nil?
|
|
43
|
+
|
|
44
|
+
dependencies = context.dependencies
|
|
45
|
+
@operation_declared_variables.each do |definition, declared_variables|
|
|
46
|
+
next if declared_variables.empty?
|
|
47
|
+
|
|
48
|
+
variable_types = {} #: Hash[String, untyped]
|
|
49
|
+
checked_fragments = {}.compare_by_identity
|
|
50
|
+
dependencies[definition].each do |fragment_definition|
|
|
51
|
+
next if checked_fragments.key?(fragment_definition)
|
|
52
|
+
checked_fragments[fragment_definition] = true
|
|
53
|
+
usages = fragment_usages[fragment_definition]
|
|
54
|
+
next if usages.nil?
|
|
55
|
+
|
|
56
|
+
usages.each do |usage|
|
|
57
|
+
var_defn_ast = declared_variables[usage.variable_name]
|
|
58
|
+
# If it's undefined, VariablesAreUsedAndDefined adds an error
|
|
59
|
+
next if var_defn_ast.nil?
|
|
60
|
+
var_type = variable_types.fetch(usage.variable_name) { variable_types[usage.variable_name] = usage_variable_type(var_defn_ast) }
|
|
61
|
+
next if var_type.nil?
|
|
62
|
+
# The result depends only on the usage and the variable type, so check each pair once.
|
|
63
|
+
# (`type_from_ast` returns the same object for the same type.)
|
|
64
|
+
checked = (usage.checked_variable_types ||= {}.compare_by_identity)
|
|
65
|
+
next if checked.key?(var_type)
|
|
66
|
+
checked[var_type] = true
|
|
67
|
+
validate_usage(usage.argument_owner, usage.arg_node, var_defn_ast, usage.list_depth, path: usage.path, var_type: var_type)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
21
70
|
end
|
|
22
|
-
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def on_argument(node, parent)
|
|
74
|
+
variables = variables_in_value(node.value, 0, nil)
|
|
23
75
|
|
|
24
|
-
if
|
|
76
|
+
if variables
|
|
25
77
|
argument_owner = case parent
|
|
26
78
|
when GraphQL::Language::Nodes::Field
|
|
27
79
|
context.field_definition
|
|
@@ -39,11 +91,38 @@ module GraphQL
|
|
|
39
91
|
raise("Unexpected argument parent: #{parent}")
|
|
40
92
|
end
|
|
41
93
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
94
|
+
if (fragment_definition = @variable_usages_fragment_definition)
|
|
95
|
+
if argument_owner
|
|
96
|
+
usages = ((@fragment_variable_usages ||= {}.compare_by_identity)[fragment_definition] ||= [])
|
|
97
|
+
path = context.path
|
|
98
|
+
variables.each do |(variable, list_depth)|
|
|
99
|
+
usages << FragmentVariableUsage.new(argument_owner, node, variable.name, list_depth, path)
|
|
100
|
+
# Previous versions checked a fragment against the last operation before it
|
|
101
|
+
if @allow_legacy_invalid_variable_usages != false && (var_defn_ast = @declared_variables[variable.name])
|
|
102
|
+
add_legacy_error(argument_owner, node, var_defn_ast, list_depth)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
elsif argument_owner
|
|
107
|
+
variables.each do |(variable, list_depth)|
|
|
108
|
+
var_defn_ast = @declared_variables[variable.name]
|
|
109
|
+
# Might be undefined :(
|
|
110
|
+
# VariablesAreUsedAndDefined can't finalize its search until the end of the document.
|
|
111
|
+
next if var_defn_ast.nil?
|
|
112
|
+
|
|
113
|
+
legacy_reported = false
|
|
114
|
+
if @allow_legacy_invalid_variable_usages != false
|
|
115
|
+
# The legacy check is the same, except for a `= null` default or a variable in a nested or mixed list
|
|
116
|
+
if var_defn_ast.default_value.is_a?(GraphQL::Language::Nodes::NullValue) ||
|
|
117
|
+
list_depth > 1 ||
|
|
118
|
+
(list_depth == 1 && depth_of_array(node.value) != 1)
|
|
119
|
+
add_legacy_error(argument_owner, node, var_defn_ast, list_depth)
|
|
120
|
+
else
|
|
121
|
+
legacy_reported = true
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
validate_usage(argument_owner, node, var_defn_ast, list_depth, legacy_reported: legacy_reported)
|
|
125
|
+
end
|
|
47
126
|
end
|
|
48
127
|
end
|
|
49
128
|
super
|
|
@@ -51,21 +130,76 @@ module GraphQL
|
|
|
51
130
|
|
|
52
131
|
private
|
|
53
132
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
133
|
+
# Variables inside input objects are found when their own arguments are visited.
|
|
134
|
+
#: (untyped value, Integer list_depth, Array[[GraphQL::Language::Nodes::VariableIdentifier, Integer]]? variables) -> Array[[GraphQL::Language::Nodes::VariableIdentifier, Integer]]?
|
|
135
|
+
def variables_in_value(value, list_depth, variables)
|
|
136
|
+
case value
|
|
137
|
+
when GraphQL::Language::Nodes::VariableIdentifier
|
|
138
|
+
(variables ||= []) << [value, list_depth]
|
|
139
|
+
when Array
|
|
140
|
+
value.each { |item| variables = variables_in_value(item, list_depth + 1, variables) }
|
|
58
141
|
end
|
|
59
|
-
|
|
142
|
+
variables
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
#: (GraphQL::Language::Nodes::VariableDefinition ast_var, ?legacy: bool) -> untyped
|
|
146
|
+
def usage_variable_type(ast_var, legacy: false)
|
|
147
|
+
var_type = context.schema.type_from_ast(ast_var.type, context: context)
|
|
148
|
+
return nil if var_type.nil?
|
|
149
|
+
default_value = ast_var.default_value
|
|
150
|
+
# An explicit `= null` default doesn't make the variable non-null (but previous versions treated it as non-null)
|
|
151
|
+
if !default_value.nil? && (legacy || !default_value.is_a?(GraphQL::Language::Nodes::NullValue))
|
|
60
152
|
unless var_type.kind.non_null?
|
|
61
153
|
# If the value is required, but the argument is not,
|
|
62
|
-
# and yet there's a non-
|
|
154
|
+
# and yet there's a non-null default, then we impliclty
|
|
63
155
|
# make the argument also a required type.
|
|
64
156
|
var_type = var_type.to_non_null_type
|
|
65
157
|
end
|
|
66
158
|
end
|
|
159
|
+
var_type
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# `legacy_reported:` is true when the legacy check has the same result, so an error isn't a legacy invalid usage.
|
|
163
|
+
#: (untyped argument_owner, GraphQL::Language::Nodes::Argument arg_node, GraphQL::Language::Nodes::VariableDefinition ast_var, Integer list_depth, ?path: Array[String]?, ?var_type: untyped, ?legacy_reported: bool) -> void
|
|
164
|
+
def validate_usage(argument_owner, arg_node, ast_var, list_depth, path: nil, var_type: usage_variable_type(ast_var), legacy_reported: false)
|
|
165
|
+
return if var_type.nil?
|
|
67
166
|
|
|
68
167
|
arg_defn = @types.argument(argument_owner, arg_node.name)
|
|
168
|
+
error_message = usage_error(arg_defn, var_type, list_depth)
|
|
169
|
+
return if error_message.nil?
|
|
170
|
+
|
|
171
|
+
message_override = nil
|
|
172
|
+
if @allow_legacy_invalid_variable_usages != false && !legacy_reported
|
|
173
|
+
# The legacy check already added its error for this argument and variable
|
|
174
|
+
return if @legacy_errors&.dig(arg_node, ast_var.name)
|
|
175
|
+
|
|
176
|
+
if @allow_legacy_invalid_variable_usages == true
|
|
177
|
+
legacy_handling = @schema.legacy_invalid_variable_usages(context.query, ast_var, arg_node)
|
|
178
|
+
case legacy_handling
|
|
179
|
+
when nil
|
|
180
|
+
return
|
|
181
|
+
when :return_validation_error
|
|
182
|
+
# Add the error below
|
|
183
|
+
when String
|
|
184
|
+
message_override = legacy_handling
|
|
185
|
+
else
|
|
186
|
+
raise GraphQL::Error, "#{@schema}.legacy_invalid_variable_usages returned unexpected value: #{legacy_handling.inspect}. Expected `nil`, String, or `:return_validation_error`."
|
|
187
|
+
end
|
|
188
|
+
else
|
|
189
|
+
context.query.logger.warn <<~WARN
|
|
190
|
+
GraphQL-Ruby encountered an invalid variable usage in this query: `$#{ast_var.name}` (at #{ast_var.line}:#{ast_var.col}) for argument `#{arg_node.name}` (at #{arg_node.line}:#{arg_node.col}).
|
|
191
|
+
This will return an error in future GraphQL-Ruby versions, as per the GraphQL specification
|
|
192
|
+
Learn about migrating here: https://graphql-ruby.org/api-doc/#{GraphQL::VERSION}/GraphQL/Schema.html#allow_legacy_invalid_variable_usages-class_method
|
|
193
|
+
WARN
|
|
194
|
+
return
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
create_error(error_message, wrap_var_type_in_lists(var_type, list_depth), ast_var, arg_defn, arg_node, path, message_override)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
#: (untyped arg_defn, untyped var_type, Integer list_depth) -> String?
|
|
202
|
+
def usage_error(arg_defn, var_type, list_depth)
|
|
69
203
|
arg_defn_type = arg_defn.type
|
|
70
204
|
|
|
71
205
|
# If the argument is non-null, but it was given a default value,
|
|
@@ -77,52 +211,43 @@ module GraphQL
|
|
|
77
211
|
var_inner_type = var_type.unwrap
|
|
78
212
|
arg_inner_type = arg_defn_type.unwrap
|
|
79
213
|
|
|
80
|
-
var_type =
|
|
214
|
+
var_type = wrap_var_type_in_lists(var_type, list_depth)
|
|
81
215
|
|
|
82
216
|
if var_inner_type != arg_inner_type
|
|
83
|
-
|
|
217
|
+
"Type mismatch"
|
|
84
218
|
elsif list_dimension(var_type) != list_dimension(arg_defn_type)
|
|
85
|
-
|
|
219
|
+
"List dimension mismatch"
|
|
86
220
|
elsif !non_null_levels_match(arg_defn_type, var_type)
|
|
87
|
-
|
|
221
|
+
"Nullability mismatch"
|
|
88
222
|
end
|
|
89
223
|
end
|
|
90
224
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
))
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
def wrap_var_type_with_depth_of_arg(var_type, arg_node)
|
|
103
|
-
arg_node_value = arg_node.value
|
|
104
|
-
return var_type unless arg_node_value.is_a?(Array)
|
|
105
|
-
new_var_type = var_type
|
|
225
|
+
# Add the error which previous versions added for this usage, if any, so that the legacy behavior rejects the same documents.
|
|
226
|
+
# They didn't check variables in nested lists, used the depth of the whole list value for each variable in it,
|
|
227
|
+
# and treated a `= null` default as non-null.
|
|
228
|
+
#: (untyped argument_owner, GraphQL::Language::Nodes::Argument arg_node, GraphQL::Language::Nodes::VariableDefinition ast_var, Integer list_depth) -> void
|
|
229
|
+
def add_legacy_error(argument_owner, arg_node, ast_var, list_depth)
|
|
230
|
+
return if list_depth > 1
|
|
231
|
+
var_type = usage_variable_type(ast_var, legacy: true)
|
|
232
|
+
return if var_type.nil?
|
|
106
233
|
|
|
107
|
-
depth_of_array(
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
end
|
|
234
|
+
list_depth = depth_of_array(arg_node.value) if list_depth == 1
|
|
235
|
+
arg_defn = @types.argument(argument_owner, arg_node.name)
|
|
236
|
+
error_message = usage_error(arg_defn, var_type, list_depth)
|
|
237
|
+
return if error_message.nil?
|
|
112
238
|
|
|
113
|
-
|
|
239
|
+
((@legacy_errors ||= {}.compare_by_identity)[arg_node] ||= {})[ast_var.name] = true
|
|
240
|
+
create_error(error_message, wrap_var_type_in_lists(var_type, list_depth), ast_var, arg_defn, arg_node, nil, nil)
|
|
114
241
|
end
|
|
115
242
|
|
|
116
|
-
#
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
243
|
+
# The maximum depth of list literals in `value`
|
|
244
|
+
#: (untyped value) -> Integer
|
|
245
|
+
def depth_of_array(value)
|
|
246
|
+
if value.is_a?(Array)
|
|
120
247
|
max_child_depth = 0
|
|
121
|
-
|
|
248
|
+
value.each do |item|
|
|
122
249
|
item_depth = depth_of_array(item)
|
|
123
|
-
if item_depth > max_child_depth
|
|
124
|
-
max_child_depth = item_depth
|
|
125
|
-
end
|
|
250
|
+
max_child_depth = item_depth if item_depth > max_child_depth
|
|
126
251
|
end
|
|
127
252
|
1 + max_child_depth
|
|
128
253
|
else
|
|
@@ -130,6 +255,37 @@ module GraphQL
|
|
|
130
255
|
end
|
|
131
256
|
end
|
|
132
257
|
|
|
258
|
+
#: (String error_message, untyped var_type, GraphQL::Language::Nodes::VariableDefinition ast_var, untyped arg_defn, GraphQL::Language::Nodes::Argument arg_node, Array[String]? path, String? message_override) -> void
|
|
259
|
+
def create_error(error_message, var_type, ast_var, arg_defn, arg_node, path, message_override)
|
|
260
|
+
message = "#{error_message} on variable $#{ast_var.name} and argument #{arg_node.name} (#{var_type.to_type_signature} / #{arg_defn.type.to_type_signature})"
|
|
261
|
+
if path
|
|
262
|
+
# Many operations can use one fragment, so add each error only once.
|
|
263
|
+
reported = (@reported_fragment_variable_errors ||= {}.compare_by_identity)[arg_node] ||= {}
|
|
264
|
+
return if reported.key?(message)
|
|
265
|
+
reported[message] = true
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
add_error(GraphQL::StaticValidation::VariableUsagesAreAllowedError.new(
|
|
269
|
+
message_override || message,
|
|
270
|
+
nodes: arg_node,
|
|
271
|
+
name: ast_var.name,
|
|
272
|
+
type: var_type.to_type_signature,
|
|
273
|
+
argument: arg_node.name,
|
|
274
|
+
error: error_message
|
|
275
|
+
), path: path)
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# A variable in list literals is used as a list item, so wrap its type in one list for each list literal.
|
|
279
|
+
#: (untyped var_type, Integer list_depth) -> untyped
|
|
280
|
+
def wrap_var_type_in_lists(var_type, list_depth)
|
|
281
|
+
list_depth.times do
|
|
282
|
+
# Since the array _is_ present, treat it like a non-null type
|
|
283
|
+
# (It satisfies a non-null requirement AND a nullable requirement)
|
|
284
|
+
var_type = var_type.to_list_type.to_non_null_type
|
|
285
|
+
end
|
|
286
|
+
var_type
|
|
287
|
+
end
|
|
288
|
+
|
|
133
289
|
def list_dimension(type)
|
|
134
290
|
if type.kind.list?
|
|
135
291
|
1 + list_dimension(type.of_type)
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
# typed: true
|
|
2
3
|
module GraphQL
|
|
3
4
|
module StaticValidation
|
|
5
|
+
#--
|
|
6
|
+
# @requires_ancestor: GraphQL::StaticValidation::BaseVisitor
|
|
4
7
|
module VariablesAreInputTypes
|
|
5
8
|
def on_variable_definition(node, parent)
|
|
6
9
|
type_name = get_type_name(node.type)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
# typed: true
|
|
2
3
|
module GraphQL
|
|
3
4
|
module StaticValidation
|
|
4
5
|
# The problem is
|
|
@@ -11,6 +12,8 @@ module GraphQL
|
|
|
11
12
|
# - re-visiting the AST for each validator
|
|
12
13
|
# - allowing validators to say `followSpreads: true`
|
|
13
14
|
#
|
|
15
|
+
#--
|
|
16
|
+
# @requires_ancestor: GraphQL::StaticValidation::BaseVisitor
|
|
14
17
|
module VariablesAreUsedAndDefined
|
|
15
18
|
class VariableUsage
|
|
16
19
|
attr_accessor :ast_node, :used_by, :declared_by, :path
|
|
@@ -89,13 +92,13 @@ module GraphQL
|
|
|
89
92
|
private
|
|
90
93
|
|
|
91
94
|
# Follow spreads in `node`, looking them up from `spreads_for_context` and finding their match in `fragment_definitions`.
|
|
92
|
-
# Use those fragments to update
|
|
95
|
+
# Use those fragments to update [VariableUsage](rdoc-ref:VariableUsage)s in `parent_variables`.
|
|
93
96
|
# Avoid infinite loops by skipping anything in `visited_fragments`.
|
|
94
97
|
def follow_spreads(node, parent_variables, spreads_for_context, fragment_definitions, visited_fragments)
|
|
95
98
|
spreads = spreads_for_context[node] - visited_fragments
|
|
96
99
|
spreads.each do |spread_name|
|
|
97
|
-
def_node = nil
|
|
98
|
-
variables = nil
|
|
100
|
+
def_node = nil #: untyped
|
|
101
|
+
variables = nil #: untyped
|
|
99
102
|
# Implement `.find` by hand to avoid Ruby's internal allocations
|
|
100
103
|
fragment_definitions.each do |frag_def_node, vars|
|
|
101
104
|
if frag_def_node.name == spread_name
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
# typed: true
|
|
2
3
|
module GraphQL
|
|
3
4
|
module StaticValidation
|
|
4
5
|
# The validation context gets passed to each validator.
|
|
5
6
|
#
|
|
6
|
-
# It exposes a
|
|
7
|
+
# It exposes a [GraphQL::Language::Visitor](rdoc-ref:GraphQL::Language::Visitor) where validators may add hooks. ([Language::Visitor#visit](rdoc-ref:Language::Visitor#visit) is called in [Validator#validate](rdoc-ref:Validator#validate))
|
|
7
8
|
#
|
|
8
9
|
# It provides access to the schema & fragments which validators may read from.
|
|
9
10
|
#
|
|
@@ -52,7 +53,7 @@ module GraphQL
|
|
|
52
53
|
|
|
53
54
|
def did_you_mean_suggestion(name, options)
|
|
54
55
|
if did_you_mean = schema.did_you_mean
|
|
55
|
-
suggestions = did_you_mean
|
|
56
|
+
suggestions = did_you_mean.const_get(:SpellChecker).new(dictionary: options).correct(name)
|
|
56
57
|
case suggestions.size
|
|
57
58
|
when 0
|
|
58
59
|
""
|
|
@@ -1,33 +1,52 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
# typed: true
|
|
2
3
|
require "timeout"
|
|
3
4
|
|
|
4
5
|
module GraphQL
|
|
5
6
|
module StaticValidation
|
|
6
|
-
# Initialized with a
|
|
7
|
+
# Initialized with a [GraphQL::Schema](rdoc-ref:GraphQL::Schema), then it can validate [GraphQL::Language::Nodes::Document](rdoc-ref:GraphQL::Language::Nodes::Document) nodes based on that schema.
|
|
7
8
|
#
|
|
8
|
-
# By default, it's used by
|
|
9
|
+
# By default, it's used by [GraphQL::Query](rdoc-ref:GraphQL::Query)
|
|
9
10
|
#
|
|
10
|
-
#
|
|
11
|
-
# validator = GraphQL::StaticValidation::Validator.new(schema: MySchema)
|
|
12
|
-
# query = GraphQL::Query.new(MySchema, query_string)
|
|
13
|
-
# errors = validator.validate(query)[:errors]
|
|
11
|
+
# **Examples**
|
|
14
12
|
#
|
|
13
|
+
# **Example: Validate a query**
|
|
14
|
+
#
|
|
15
|
+
# ```ruby
|
|
16
|
+
# validator = GraphQL::StaticValidation::Validator.new(schema: MySchema)
|
|
17
|
+
# query = GraphQL::Query.new(MySchema, query_string)
|
|
18
|
+
# errors = validator.validate(query)[:errors]
|
|
19
|
+
# ```
|
|
15
20
|
class Validator
|
|
16
|
-
#
|
|
17
|
-
#
|
|
21
|
+
# **Parameters**
|
|
22
|
+
#
|
|
23
|
+
# - `schema` (`GraphQL::Schema`)
|
|
24
|
+
# - `rules` (`Array<#validate(context)>`) — a list of rules to use when validating
|
|
25
|
+
#
|
|
26
|
+
# :call-seq:
|
|
27
|
+
# initialize(GraphQL::Schema schema:, Array[#validate(context)] rules:)
|
|
18
28
|
def initialize(schema:, rules: GraphQL::StaticValidation::ALL_RULES)
|
|
19
29
|
@schema = schema
|
|
20
30
|
@rules = rules
|
|
21
31
|
end
|
|
22
32
|
|
|
23
33
|
# Validate `query` against the schema. Returns an array of message hashes.
|
|
24
|
-
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
#
|
|
34
|
+
#
|
|
35
|
+
# **Parameters**
|
|
36
|
+
#
|
|
37
|
+
# - `query` (`GraphQL::Query`)
|
|
38
|
+
# - `validate` (`Boolean`)
|
|
39
|
+
# - `timeout` (`Float`) — Number of seconds to wait before aborting validation. Any positive number may be used, including Floats to specify fractional seconds.
|
|
40
|
+
# - `max_errors` (`Integer`) — Maximum number of errors before aborting validation. Any positive number will limit the number of errors. Defaults to nil for no limit.
|
|
41
|
+
#
|
|
42
|
+
# **Returns**
|
|
43
|
+
#
|
|
44
|
+
# - `Array<Hash>`
|
|
45
|
+
#
|
|
46
|
+
# :call-seq:
|
|
47
|
+
# validate(GraphQL::Query query, bool validate:, Float timeout:, Integer max_errors:) -> Array[Hash]
|
|
29
48
|
def validate(query, validate: true, timeout: nil, max_errors: nil)
|
|
30
|
-
errors = nil
|
|
49
|
+
errors = nil #: untyped
|
|
31
50
|
query.current_trace.begin_validate(query, validate)
|
|
32
51
|
query.current_trace.validate(validate: validate, query: query) do
|
|
33
52
|
begin_t = Time.now
|
|
@@ -70,8 +89,14 @@ module GraphQL
|
|
|
70
89
|
end
|
|
71
90
|
|
|
72
91
|
# Invoked when static validation times out.
|
|
73
|
-
#
|
|
74
|
-
#
|
|
92
|
+
#
|
|
93
|
+
# **Parameters**
|
|
94
|
+
#
|
|
95
|
+
# - `query` (`GraphQL::Query`)
|
|
96
|
+
# - `context` (`GraphQL::StaticValidation::ValidationContext`)
|
|
97
|
+
#
|
|
98
|
+
# :call-seq:
|
|
99
|
+
# handle_timeout(GraphQL::Query query, GraphQL::StaticValidation::ValidationContext context)
|
|
75
100
|
def handle_timeout(query, context)
|
|
76
101
|
context.errors << GraphQL::StaticValidation::ValidationTimeoutError.new(
|
|
77
102
|
"Timeout on validation of query"
|