graphql 1.13.24 → 2.5.11
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/lib/generators/graphql/install/mutation_root_generator.rb +2 -2
- data/lib/generators/graphql/install/templates/base_mutation.erb +2 -0
- data/lib/generators/graphql/install/templates/mutation_type.erb +2 -0
- data/lib/generators/graphql/install_generator.rb +50 -1
- data/lib/generators/graphql/mutation_delete_generator.rb +1 -1
- data/lib/generators/graphql/mutation_update_generator.rb +1 -1
- data/lib/generators/graphql/orm_mutations_base.rb +1 -1
- data/lib/generators/graphql/relay.rb +21 -18
- data/lib/generators/graphql/templates/base_argument.erb +2 -0
- data/lib/generators/graphql/templates/base_connection.erb +2 -0
- data/lib/generators/graphql/templates/base_edge.erb +2 -0
- data/lib/generators/graphql/templates/base_enum.erb +2 -0
- data/lib/generators/graphql/templates/base_field.erb +2 -0
- data/lib/generators/graphql/templates/base_input_object.erb +2 -0
- data/lib/generators/graphql/templates/base_interface.erb +2 -0
- data/lib/generators/graphql/templates/base_object.erb +2 -0
- data/lib/generators/graphql/templates/base_resolver.erb +8 -0
- data/lib/generators/graphql/templates/base_scalar.erb +2 -0
- data/lib/generators/graphql/templates/base_union.erb +2 -0
- data/lib/generators/graphql/templates/graphql_controller.erb +2 -0
- data/lib/generators/graphql/templates/loader.erb +2 -0
- data/lib/generators/graphql/templates/mutation.erb +2 -0
- data/lib/generators/graphql/templates/node_type.erb +2 -0
- data/lib/generators/graphql/templates/query_type.erb +2 -0
- data/lib/generators/graphql/templates/schema.erb +8 -0
- data/lib/generators/graphql/type_generator.rb +1 -1
- data/lib/graphql/analysis/analyzer.rb +90 -0
- data/lib/graphql/analysis/field_usage.rb +65 -28
- data/lib/graphql/analysis/max_query_complexity.rb +11 -17
- data/lib/graphql/analysis/max_query_depth.rb +13 -19
- data/lib/graphql/analysis/query_complexity.rb +236 -61
- data/lib/graphql/analysis/query_depth.rb +38 -23
- data/lib/graphql/analysis/visitor.rb +280 -0
- data/lib/graphql/analysis.rb +93 -6
- data/lib/graphql/autoload.rb +38 -0
- data/lib/graphql/backtrace/table.rb +118 -73
- data/lib/graphql/backtrace.rb +2 -25
- data/lib/graphql/coercion_error.rb +1 -9
- data/lib/graphql/current.rb +57 -0
- data/lib/graphql/dashboard/detailed_traces.rb +47 -0
- data/lib/graphql/dashboard/installable.rb +22 -0
- data/lib/graphql/dashboard/limiters.rb +93 -0
- data/lib/graphql/dashboard/operation_store.rb +199 -0
- data/lib/graphql/dashboard/statics/bootstrap-5.3.3.min.css +6 -0
- data/lib/graphql/dashboard/statics/bootstrap-5.3.3.min.js +7 -0
- data/lib/graphql/dashboard/statics/charts.min.css +1 -0
- data/lib/graphql/dashboard/statics/dashboard.css +30 -0
- data/lib/graphql/dashboard/statics/dashboard.js +143 -0
- data/lib/graphql/dashboard/statics/header-icon.png +0 -0
- data/lib/graphql/dashboard/statics/icon.png +0 -0
- data/lib/graphql/dashboard/subscriptions.rb +96 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/detailed_traces/traces/index.html.erb +45 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/landings/show.html.erb +18 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/limiters/limiters/show.html.erb +62 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/not_installed.html.erb +18 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/_form.html.erb +23 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/edit.html.erb +21 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/index.html.erb +69 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/new.html.erb +7 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/index.html.erb +39 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/show.html.erb +32 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/index.html.erb +81 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/show.html.erb +71 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/subscriptions/show.html.erb +41 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/index.html.erb +55 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/show.html.erb +40 -0
- data/lib/graphql/dashboard/views/layouts/graphql/dashboard/application.html.erb +108 -0
- data/lib/graphql/dashboard.rb +158 -0
- data/lib/graphql/dataloader/active_record_association_source.rb +84 -0
- data/lib/graphql/dataloader/active_record_source.rb +47 -0
- data/lib/graphql/dataloader/async_dataloader.rb +101 -0
- data/lib/graphql/dataloader/null_dataloader.rb +11 -2
- data/lib/graphql/dataloader/request.rb +5 -0
- data/lib/graphql/dataloader/source.rb +103 -47
- data/lib/graphql/dataloader.rb +174 -148
- data/lib/graphql/dig.rb +3 -2
- data/lib/graphql/duration_encoding_error.rb +16 -0
- data/lib/graphql/execution/errors.rb +12 -82
- data/lib/graphql/execution/interpreter/argument_value.rb +5 -1
- data/lib/graphql/execution/interpreter/arguments.rb +1 -1
- data/lib/graphql/execution/interpreter/arguments_cache.rb +30 -35
- data/lib/graphql/execution/interpreter/resolve.rb +32 -2
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +215 -0
- data/lib/graphql/execution/interpreter/runtime.rb +525 -502
- data/lib/graphql/execution/interpreter.rb +127 -81
- data/lib/graphql/execution/lazy.rb +7 -21
- data/lib/graphql/execution/lookahead.rb +133 -55
- data/lib/graphql/execution/multiplex.rb +6 -176
- data/lib/graphql/execution.rb +11 -4
- data/lib/graphql/introspection/directive_location_enum.rb +1 -1
- data/lib/graphql/introspection/directive_type.rb +1 -1
- data/lib/graphql/introspection/dynamic_fields.rb +3 -8
- data/lib/graphql/introspection/entry_points.rb +10 -17
- data/lib/graphql/introspection/field_type.rb +1 -1
- data/lib/graphql/introspection/schema_type.rb +8 -11
- data/lib/graphql/introspection/type_type.rb +13 -6
- data/lib/graphql/introspection.rb +4 -3
- data/lib/graphql/invalid_name_error.rb +1 -1
- data/lib/graphql/invalid_null_error.rb +20 -17
- data/lib/graphql/language/block_string.rb +34 -18
- data/lib/graphql/language/cache.rb +13 -0
- data/lib/graphql/language/comment.rb +18 -0
- data/lib/graphql/language/definition_slice.rb +1 -1
- data/lib/graphql/language/document_from_schema_definition.rb +114 -80
- data/lib/graphql/language/lexer.rb +375 -1489
- data/lib/graphql/language/nodes.rb +189 -104
- data/lib/graphql/language/parser.rb +807 -1941
- data/lib/graphql/language/printer.rb +366 -163
- data/lib/graphql/language/sanitized_printer.rb +21 -23
- data/lib/graphql/language/static_visitor.rb +171 -0
- data/lib/graphql/language/visitor.rb +189 -138
- data/lib/graphql/language.rb +62 -1
- data/lib/graphql/load_application_object_failed_error.rb +5 -1
- data/lib/graphql/pagination/active_record_relation_connection.rb +0 -8
- data/lib/graphql/pagination/array_connection.rb +8 -6
- data/lib/graphql/pagination/connection.rb +61 -7
- data/lib/graphql/pagination/connections.rb +3 -28
- data/lib/graphql/pagination/mongoid_relation_connection.rb +1 -2
- data/lib/graphql/pagination/relation_connection.rb +2 -0
- data/lib/graphql/query/context/scoped_context.rb +101 -0
- data/lib/graphql/query/context.rb +131 -225
- data/lib/graphql/query/input_validation_result.rb +1 -1
- data/lib/graphql/query/null_context.rb +11 -33
- data/lib/graphql/query/partial.rb +179 -0
- data/lib/graphql/query/validation_pipeline.rb +14 -37
- data/lib/graphql/query/variable_validation_error.rb +1 -1
- data/lib/graphql/query/variables.rb +6 -19
- data/lib/graphql/query.rb +162 -98
- data/lib/graphql/railtie.rb +15 -109
- data/lib/graphql/rake_task/validate.rb +1 -1
- data/lib/graphql/rake_task.rb +30 -11
- data/lib/graphql/relay/range_add.rb +9 -20
- data/lib/graphql/relay.rb +0 -15
- data/lib/graphql/rubocop/graphql/base_cop.rb +1 -1
- data/lib/graphql/rubocop/graphql/field_type_in_block.rb +144 -0
- data/lib/graphql/rubocop/graphql/root_types_in_block.rb +38 -0
- data/lib/graphql/rubocop.rb +2 -0
- data/lib/graphql/schema/addition.rb +70 -33
- data/lib/graphql/schema/always_visible.rb +15 -0
- data/lib/graphql/schema/argument.rb +104 -59
- data/lib/graphql/schema/base_64_encoder.rb +3 -5
- data/lib/graphql/schema/build_from_definition.rb +154 -74
- data/lib/graphql/schema/directive/flagged.rb +4 -2
- data/lib/graphql/schema/directive/one_of.rb +24 -0
- data/lib/graphql/schema/directive/specified_by.rb +14 -0
- data/lib/graphql/schema/directive/transform.rb +1 -1
- data/lib/graphql/schema/directive.rb +47 -24
- data/lib/graphql/schema/enum.rb +137 -65
- data/lib/graphql/schema/enum_value.rb +11 -26
- data/lib/graphql/schema/field/connection_extension.rb +6 -16
- data/lib/graphql/schema/field/scope_extension.rb +8 -1
- data/lib/graphql/schema/field.rb +399 -404
- data/lib/graphql/schema/field_extension.rb +2 -5
- data/lib/graphql/schema/find_inherited_value.rb +2 -7
- data/lib/graphql/schema/has_single_input_argument.rb +160 -0
- data/lib/graphql/schema/input_object.rb +144 -99
- data/lib/graphql/schema/interface.rb +34 -51
- data/lib/graphql/schema/introspection_system.rb +12 -26
- data/lib/graphql/schema/late_bound_type.rb +12 -2
- data/lib/graphql/schema/list.rb +3 -9
- data/lib/graphql/schema/loader.rb +4 -6
- data/lib/graphql/schema/member/base_dsl_methods.rb +32 -18
- data/lib/graphql/schema/member/build_type.rb +15 -9
- data/lib/graphql/schema/member/has_arguments.rb +192 -96
- data/lib/graphql/schema/member/has_ast_node.rb +12 -0
- data/lib/graphql/schema/member/has_dataloader.rb +62 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +18 -4
- data/lib/graphql/schema/member/has_directives.rb +81 -61
- data/lib/graphql/schema/member/has_fields.rb +119 -39
- data/lib/graphql/schema/member/has_interfaces.rb +66 -23
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +5 -1
- data/lib/graphql/schema/member/has_validators.rb +32 -6
- data/lib/graphql/schema/member/relay_shortcuts.rb +47 -2
- data/lib/graphql/schema/member/scoped.rb +19 -0
- data/lib/graphql/schema/member/type_system_helpers.rb +32 -2
- data/lib/graphql/schema/member/validates_input.rb +4 -4
- data/lib/graphql/schema/member.rb +1 -6
- data/lib/graphql/schema/mutation.rb +7 -9
- data/lib/graphql/schema/non_null.rb +1 -7
- data/lib/graphql/schema/object.rb +42 -49
- data/lib/graphql/schema/printer.rb +12 -8
- data/lib/graphql/schema/ractor_shareable.rb +79 -0
- data/lib/graphql/schema/relay_classic_mutation.rb +12 -124
- data/lib/graphql/schema/resolver/has_payload_type.rb +20 -10
- data/lib/graphql/schema/resolver.rb +96 -81
- data/lib/graphql/schema/scalar.rb +10 -30
- data/lib/graphql/schema/subscription.rb +60 -14
- data/lib/graphql/schema/timeout.rb +44 -31
- data/lib/graphql/schema/type_expression.rb +2 -2
- data/lib/graphql/schema/type_membership.rb +3 -0
- data/lib/graphql/schema/union.rb +12 -19
- data/lib/graphql/schema/unique_within_type.rb +1 -1
- data/lib/graphql/schema/validator/all_validator.rb +62 -0
- data/lib/graphql/schema/validator/required_validator.rb +60 -10
- data/lib/graphql/schema/validator.rb +5 -3
- data/lib/graphql/schema/visibility/migration.rb +188 -0
- data/lib/graphql/schema/visibility/profile.rb +445 -0
- data/lib/graphql/schema/visibility/visit.rb +190 -0
- data/lib/graphql/schema/visibility.rb +311 -0
- data/lib/graphql/schema/warden.rb +318 -94
- data/lib/graphql/schema/wrapper.rb +0 -5
- data/lib/graphql/schema.rb +1148 -1085
- data/lib/graphql/static_validation/all_rules.rb +4 -3
- data/lib/graphql/static_validation/base_visitor.rb +11 -27
- data/lib/graphql/static_validation/definition_dependencies.rb +7 -1
- data/lib/graphql/static_validation/error.rb +2 -2
- data/lib/graphql/static_validation/literal_validator.rb +24 -7
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
- data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +1 -1
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +3 -2
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +13 -7
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +14 -12
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +12 -2
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +48 -6
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +90 -27
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +10 -2
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +12 -2
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
- data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +1 -1
- data/lib/graphql/static_validation/rules/not_single_subscription_error.rb +25 -0
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
- data/lib/graphql/static_validation/rules/query_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +5 -5
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +5 -5
- data/lib/graphql/static_validation/rules/subscription_root_exists_and_single_subscription_selection.rb +26 -0
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +19 -9
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +18 -27
- data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +2 -2
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +11 -2
- data/lib/graphql/static_validation/validation_context.rb +21 -5
- data/lib/graphql/static_validation/validator.rb +12 -26
- data/lib/graphql/static_validation.rb +0 -3
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +14 -6
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +11 -5
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +40 -1
- data/lib/graphql/subscriptions/event.rb +24 -12
- data/lib/graphql/subscriptions/serialize.rb +3 -1
- data/lib/graphql/subscriptions.rb +48 -32
- data/lib/graphql/testing/helpers.rb +158 -0
- data/lib/graphql/testing.rb +2 -0
- data/lib/graphql/tracing/active_support_notifications_trace.rb +27 -0
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +1 -1
- data/lib/graphql/tracing/appoptics_trace.rb +259 -0
- data/lib/graphql/tracing/appoptics_tracing.rb +9 -2
- data/lib/graphql/tracing/appsignal_trace.rb +54 -0
- data/lib/graphql/tracing/appsignal_tracing.rb +2 -0
- data/lib/graphql/tracing/call_legacy_tracers.rb +66 -0
- data/lib/graphql/tracing/data_dog_trace.rb +71 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +3 -0
- data/lib/graphql/tracing/detailed_trace/memory_backend.rb +60 -0
- data/lib/graphql/tracing/detailed_trace/redis_backend.rb +72 -0
- data/lib/graphql/tracing/detailed_trace.rb +93 -0
- data/lib/graphql/{execution/instrumentation.rb → tracing/legacy_hooks_trace.rb} +11 -28
- data/lib/graphql/tracing/legacy_trace.rb +12 -0
- data/lib/graphql/tracing/monitor_trace.rb +283 -0
- data/lib/graphql/tracing/new_relic_trace.rb +68 -0
- data/lib/graphql/tracing/new_relic_tracing.rb +2 -0
- data/lib/graphql/tracing/notifications_trace.rb +195 -0
- data/lib/graphql/tracing/notifications_tracing.rb +2 -0
- data/lib/graphql/tracing/null_trace.rb +9 -0
- data/lib/graphql/tracing/perfetto_trace/trace.proto +141 -0
- data/lib/graphql/tracing/perfetto_trace/trace_pb.rb +33 -0
- data/lib/graphql/tracing/perfetto_trace.rb +734 -0
- data/lib/graphql/tracing/platform_trace.rb +123 -0
- data/lib/graphql/tracing/platform_tracing.rb +28 -41
- data/lib/graphql/tracing/{prometheus_tracing → prometheus_trace}/graphql_collector.rb +6 -2
- data/lib/graphql/tracing/prometheus_trace.rb +93 -0
- data/lib/graphql/tracing/prometheus_tracing.rb +5 -3
- data/lib/graphql/tracing/scout_trace.rb +49 -0
- data/lib/graphql/tracing/scout_tracing.rb +2 -0
- data/lib/graphql/tracing/sentry_trace.rb +80 -0
- data/lib/graphql/tracing/statsd_trace.rb +48 -0
- data/lib/graphql/tracing/statsd_tracing.rb +2 -0
- data/lib/graphql/tracing/trace.rb +186 -0
- data/lib/graphql/tracing.rb +32 -52
- data/lib/graphql/type_kinds.rb +8 -4
- data/lib/graphql/types/iso_8601_date.rb +4 -1
- data/lib/graphql/types/iso_8601_date_time.rb +4 -0
- data/lib/graphql/types/iso_8601_duration.rb +77 -0
- data/lib/graphql/types/relay/base_connection.rb +16 -6
- data/lib/graphql/types/relay/connection_behaviors.rb +65 -23
- data/lib/graphql/types/relay/edge_behaviors.rb +33 -5
- data/lib/graphql/types/relay/node_behaviors.rb +12 -2
- data/lib/graphql/types/relay/page_info_behaviors.rb +11 -2
- data/lib/graphql/types/relay.rb +0 -3
- data/lib/graphql/types/string.rb +1 -1
- data/lib/graphql/types.rb +18 -10
- data/lib/graphql/unauthorized_enum_value_error.rb +13 -0
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +76 -123
- data/readme.md +13 -3
- metadata +225 -142
- data/lib/graphql/analysis/analyze_query.rb +0 -98
- data/lib/graphql/analysis/ast/analyzer.rb +0 -84
- data/lib/graphql/analysis/ast/field_usage.rb +0 -55
- data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -23
- data/lib/graphql/analysis/ast/max_query_depth.rb +0 -22
- data/lib/graphql/analysis/ast/query_complexity.rb +0 -230
- data/lib/graphql/analysis/ast/query_depth.rb +0 -56
- data/lib/graphql/analysis/ast/visitor.rb +0 -269
- data/lib/graphql/analysis/ast.rb +0 -91
- data/lib/graphql/analysis/reducer_state.rb +0 -48
- data/lib/graphql/argument.rb +0 -131
- data/lib/graphql/authorization.rb +0 -82
- data/lib/graphql/backtrace/inspect_result.rb +0 -50
- data/lib/graphql/backtrace/legacy_tracer.rb +0 -56
- data/lib/graphql/backtrace/tracer.rb +0 -81
- data/lib/graphql/backwards_compatibility.rb +0 -61
- data/lib/graphql/base_type.rb +0 -232
- data/lib/graphql/boolean_type.rb +0 -2
- data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
- data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
- data/lib/graphql/compatibility/execution_specification.rb +0 -436
- data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
- data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -215
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -87
- data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
- data/lib/graphql/compatibility/query_parser_specification.rb +0 -266
- data/lib/graphql/compatibility/schema_parser_specification.rb +0 -682
- data/lib/graphql/compatibility.rb +0 -5
- data/lib/graphql/define/assign_argument.rb +0 -12
- data/lib/graphql/define/assign_connection.rb +0 -13
- data/lib/graphql/define/assign_enum_value.rb +0 -18
- data/lib/graphql/define/assign_global_id_field.rb +0 -11
- data/lib/graphql/define/assign_mutation_function.rb +0 -34
- data/lib/graphql/define/assign_object_field.rb +0 -42
- data/lib/graphql/define/defined_object_proxy.rb +0 -53
- data/lib/graphql/define/instance_definable.rb +0 -255
- data/lib/graphql/define/no_definition_error.rb +0 -7
- data/lib/graphql/define/non_null_with_bang.rb +0 -16
- data/lib/graphql/define/type_definer.rb +0 -31
- data/lib/graphql/define.rb +0 -31
- data/lib/graphql/deprecated_dsl.rb +0 -55
- data/lib/graphql/deprecation.rb +0 -9
- data/lib/graphql/directive/deprecated_directive.rb +0 -2
- data/lib/graphql/directive/include_directive.rb +0 -2
- data/lib/graphql/directive/skip_directive.rb +0 -2
- data/lib/graphql/directive.rb +0 -107
- data/lib/graphql/enum_type.rb +0 -133
- data/lib/graphql/execution/execute.rb +0 -333
- data/lib/graphql/execution/flatten.rb +0 -40
- data/lib/graphql/execution/lazy/resolve.rb +0 -91
- data/lib/graphql/execution/typecast.rb +0 -50
- data/lib/graphql/field/resolve.rb +0 -59
- data/lib/graphql/field.rb +0 -226
- data/lib/graphql/filter.rb +0 -53
- data/lib/graphql/float_type.rb +0 -2
- data/lib/graphql/function.rb +0 -128
- data/lib/graphql/id_type.rb +0 -2
- data/lib/graphql/input_object_type.rb +0 -138
- data/lib/graphql/int_type.rb +0 -2
- data/lib/graphql/interface_type.rb +0 -72
- data/lib/graphql/internal_representation/document.rb +0 -27
- data/lib/graphql/internal_representation/node.rb +0 -206
- data/lib/graphql/internal_representation/print.rb +0 -51
- data/lib/graphql/internal_representation/rewrite.rb +0 -184
- data/lib/graphql/internal_representation/scope.rb +0 -88
- data/lib/graphql/internal_representation/visit.rb +0 -36
- data/lib/graphql/internal_representation.rb +0 -7
- data/lib/graphql/language/lexer.rl +0 -260
- data/lib/graphql/language/parser.y +0 -550
- data/lib/graphql/language/token.rb +0 -34
- data/lib/graphql/list_type.rb +0 -80
- data/lib/graphql/non_null_type.rb +0 -71
- data/lib/graphql/object_type.rb +0 -130
- data/lib/graphql/query/arguments.rb +0 -189
- data/lib/graphql/query/arguments_cache.rb +0 -24
- data/lib/graphql/query/executor.rb +0 -52
- data/lib/graphql/query/literal_input.rb +0 -136
- data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
- data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
- data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
- data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
- data/lib/graphql/query/serial_execution.rb +0 -40
- data/lib/graphql/relay/array_connection.rb +0 -83
- data/lib/graphql/relay/base_connection.rb +0 -189
- data/lib/graphql/relay/connection_instrumentation.rb +0 -54
- data/lib/graphql/relay/connection_resolve.rb +0 -43
- data/lib/graphql/relay/connection_type.rb +0 -54
- data/lib/graphql/relay/edge.rb +0 -27
- data/lib/graphql/relay/edge_type.rb +0 -19
- data/lib/graphql/relay/edges_instrumentation.rb +0 -39
- data/lib/graphql/relay/global_id_resolve.rb +0 -17
- data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
- data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
- data/lib/graphql/relay/mutation/resolve.rb +0 -56
- data/lib/graphql/relay/mutation/result.rb +0 -38
- data/lib/graphql/relay/mutation.rb +0 -106
- data/lib/graphql/relay/node.rb +0 -39
- data/lib/graphql/relay/page_info.rb +0 -7
- data/lib/graphql/relay/relation_connection.rb +0 -188
- data/lib/graphql/relay/type_extensions.rb +0 -32
- data/lib/graphql/scalar_type.rb +0 -91
- data/lib/graphql/schema/base_64_bp.rb +0 -26
- data/lib/graphql/schema/catchall_middleware.rb +0 -35
- data/lib/graphql/schema/default_parse_error.rb +0 -10
- data/lib/graphql/schema/default_type_error.rb +0 -17
- data/lib/graphql/schema/invalid_type_error.rb +0 -7
- data/lib/graphql/schema/member/accepts_definition.rb +0 -164
- data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -58
- data/lib/graphql/schema/member/instrumentation.rb +0 -131
- data/lib/graphql/schema/middleware_chain.rb +0 -82
- data/lib/graphql/schema/null_mask.rb +0 -11
- data/lib/graphql/schema/possible_types.rb +0 -44
- data/lib/graphql/schema/rescue_middleware.rb +0 -60
- data/lib/graphql/schema/timeout_middleware.rb +0 -88
- data/lib/graphql/schema/traversal.rb +0 -228
- data/lib/graphql/schema/validation.rb +0 -313
- data/lib/graphql/static_validation/default_visitor.rb +0 -15
- data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
- data/lib/graphql/static_validation/rules/subscription_root_exists.rb +0 -17
- data/lib/graphql/static_validation/type_stack.rb +0 -216
- data/lib/graphql/string_type.rb +0 -2
- data/lib/graphql/subscriptions/instrumentation.rb +0 -79
- data/lib/graphql/subscriptions/subscription_root.rb +0 -76
- data/lib/graphql/tracing/skylight_tracing.rb +0 -70
- data/lib/graphql/types/relay/default_relay.rb +0 -31
- data/lib/graphql/types/relay/node_field.rb +0 -24
- data/lib/graphql/types/relay/nodes_field.rb +0 -43
- data/lib/graphql/union_type.rb +0 -115
- data/lib/graphql/upgrader/member.rb +0 -937
- data/lib/graphql/upgrader/schema.rb +0 -38
@@ -3,7 +3,7 @@ module GraphQL
|
|
3
3
|
module StaticValidation
|
4
4
|
# Default rules for {GraphQL::StaticValidation::Validator}
|
5
5
|
#
|
6
|
-
# Order is important here. Some validators
|
6
|
+
# Order is important here. Some validators skip later hooks.
|
7
7
|
# which stops the visit on that node. That way it doesn't try to find fields on types that
|
8
8
|
# don't exist, etc.
|
9
9
|
ALL_RULES = [
|
@@ -34,8 +34,9 @@ module GraphQL
|
|
34
34
|
GraphQL::StaticValidation::VariableUsagesAreAllowed,
|
35
35
|
GraphQL::StaticValidation::MutationRootExists,
|
36
36
|
GraphQL::StaticValidation::QueryRootExists,
|
37
|
-
GraphQL::StaticValidation::
|
37
|
+
GraphQL::StaticValidation::SubscriptionRootExistsAndSingleSubscriptionSelection,
|
38
38
|
GraphQL::StaticValidation::InputObjectNamesAreUnique,
|
39
|
-
|
39
|
+
GraphQL::StaticValidation::OneOfInputObjectsAreValid,
|
40
|
+
].freeze
|
40
41
|
end
|
41
42
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module GraphQL
|
3
3
|
module StaticValidation
|
4
|
-
class BaseVisitor < GraphQL::Language::
|
4
|
+
class BaseVisitor < GraphQL::Language::StaticVisitor
|
5
5
|
def initialize(document, context)
|
6
6
|
@path = []
|
7
7
|
@object_types = []
|
@@ -10,15 +10,11 @@ module GraphQL
|
|
10
10
|
@argument_definitions = []
|
11
11
|
@directive_definitions = []
|
12
12
|
@context = context
|
13
|
+
@types = context.query.types
|
13
14
|
@schema = context.schema
|
14
15
|
super(document)
|
15
16
|
end
|
16
17
|
|
17
|
-
# This will be overwritten by {InternalRepresentation::Rewrite} if it's included
|
18
|
-
def rewrite_document
|
19
|
-
nil
|
20
|
-
end
|
21
|
-
|
22
18
|
attr_reader :context
|
23
19
|
|
24
20
|
# @return [Array<GraphQL::ObjectType>] Types whose scope we've entered
|
@@ -32,22 +28,13 @@ module GraphQL
|
|
32
28
|
# Build a class to visit the AST and perform validation,
|
33
29
|
# or use a pre-built class if rules is `ALL_RULES` or empty.
|
34
30
|
# @param rules [Array<Module, Class>]
|
35
|
-
# @param rewrite [Boolean] if `false`, don't include rewrite
|
36
31
|
# @return [Class] A class for validating `rules` during visitation
|
37
|
-
def self.including_rules(rules
|
32
|
+
def self.including_rules(rules)
|
38
33
|
if rules.empty?
|
39
|
-
|
40
|
-
|
41
|
-
else
|
42
|
-
# It's not doing _anything?!?_
|
43
|
-
BaseVisitor
|
44
|
-
end
|
34
|
+
# It's not doing _anything?!?_
|
35
|
+
BaseVisitor
|
45
36
|
elsif rules == ALL_RULES
|
46
|
-
|
47
|
-
DefaultVisitor
|
48
|
-
else
|
49
|
-
InterpreterVisitor
|
50
|
-
end
|
37
|
+
InterpreterVisitor
|
51
38
|
else
|
52
39
|
visitor_class = Class.new(self) do
|
53
40
|
include(GraphQL::StaticValidation::DefinitionDependencies)
|
@@ -60,9 +47,6 @@ module GraphQL
|
|
60
47
|
end
|
61
48
|
end
|
62
49
|
|
63
|
-
if rewrite
|
64
|
-
visitor_class.include(GraphQL::InternalRepresentation::Rewrite)
|
65
|
-
end
|
66
50
|
visitor_class.include(ContextMethods)
|
67
51
|
visitor_class
|
68
52
|
end
|
@@ -94,7 +78,7 @@ module GraphQL
|
|
94
78
|
|
95
79
|
def on_field(node, parent)
|
96
80
|
parent_type = @object_types.last
|
97
|
-
field_definition = @
|
81
|
+
field_definition = @types.field(parent_type, node.name)
|
98
82
|
@field_definitions.push(field_definition)
|
99
83
|
if !field_definition.nil?
|
100
84
|
next_object_type = field_definition.type.unwrap
|
@@ -120,14 +104,14 @@ module GraphQL
|
|
120
104
|
argument_defn = if (arg = @argument_definitions.last)
|
121
105
|
arg_type = arg.type.unwrap
|
122
106
|
if arg_type.kind.input_object?
|
123
|
-
@
|
107
|
+
@types.argument(arg_type, node.name)
|
124
108
|
else
|
125
109
|
nil
|
126
110
|
end
|
127
111
|
elsif (directive_defn = @directive_definitions.last)
|
128
|
-
@
|
112
|
+
@types.argument(directive_defn, node.name)
|
129
113
|
elsif (field_defn = @field_definitions.last)
|
130
|
-
@
|
114
|
+
@types.argument(field_defn, node.name)
|
131
115
|
else
|
132
116
|
nil
|
133
117
|
end
|
@@ -187,7 +171,7 @@ module GraphQL
|
|
187
171
|
|
188
172
|
def on_fragment_with_type(node)
|
189
173
|
object_type = if node.type
|
190
|
-
@
|
174
|
+
@types.type(node.type.name)
|
191
175
|
else
|
192
176
|
@object_types.last
|
193
177
|
end
|
@@ -127,8 +127,14 @@ module GraphQL
|
|
127
127
|
# same name as if they were the same name. If _any_ of the fragments
|
128
128
|
# with that name has a dependency, we record it.
|
129
129
|
independent_fragment_nodes = @defdep_fragment_definitions.values.flatten - @defdep_immediate_dependencies.keys
|
130
|
-
|
130
|
+
visited_fragment_names = Set.new
|
131
131
|
while fragment_node = independent_fragment_nodes.pop
|
132
|
+
if visited_fragment_names.add?(fragment_node.name)
|
133
|
+
# this is a new fragment name
|
134
|
+
else
|
135
|
+
# this is a duplicate fragment name
|
136
|
+
next
|
137
|
+
end
|
132
138
|
loops += 1
|
133
139
|
if loops > max_loops
|
134
140
|
raise("Resolution loops exceeded the number of definitions; infinite loop detected. (Max: #{max_loops}, Current: #{loops})")
|
@@ -5,7 +5,7 @@ module GraphQL
|
|
5
5
|
class LiteralValidator
|
6
6
|
def initialize(context:)
|
7
7
|
@context = context
|
8
|
-
@
|
8
|
+
@types = context.types
|
9
9
|
@invalid_response = GraphQL::Query::InputValidationResult.new(valid: false, problems: [])
|
10
10
|
@valid_response = GraphQL::Query::InputValidationResult.new(valid: true, problems: [])
|
11
11
|
end
|
@@ -18,6 +18,19 @@ module GraphQL
|
|
18
18
|
|
19
19
|
private
|
20
20
|
|
21
|
+
def replace_nulls_in(ast_value)
|
22
|
+
case ast_value
|
23
|
+
when Array
|
24
|
+
ast_value.map { |v| replace_nulls_in(v) }
|
25
|
+
when GraphQL::Language::Nodes::InputObject
|
26
|
+
ast_value.to_h
|
27
|
+
when GraphQL::Language::Nodes::NullValue
|
28
|
+
nil
|
29
|
+
else
|
30
|
+
ast_value
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
21
34
|
def recursively_validate(ast_value, type)
|
22
35
|
if type.nil?
|
23
36
|
# this means we're an undefined argument, see #present_input_field_values_are_valid
|
@@ -42,7 +55,8 @@ module GraphQL
|
|
42
55
|
@valid_response
|
43
56
|
elsif type.kind.scalar? && constant_scalar?(ast_value)
|
44
57
|
maybe_raise_if_invalid(ast_value) do
|
45
|
-
|
58
|
+
ruby_value = replace_nulls_in(ast_value)
|
59
|
+
type.validate_input(ruby_value, @context)
|
46
60
|
end
|
47
61
|
elsif type.kind.enum?
|
48
62
|
maybe_raise_if_invalid(ast_value) do
|
@@ -95,9 +109,9 @@ module GraphQL
|
|
95
109
|
def required_input_fields_are_present(type, ast_node)
|
96
110
|
# TODO - would be nice to use these to create an error message so the caller knows
|
97
111
|
# that required fields are missing
|
98
|
-
required_field_names = @
|
99
|
-
.select { |argument| argument.type.kind.non_null? &&
|
100
|
-
.map(&:name)
|
112
|
+
required_field_names = @types.arguments(type)
|
113
|
+
.select { |argument| argument.type.kind.non_null? && !argument.default_value? }
|
114
|
+
.map!(&:name)
|
101
115
|
|
102
116
|
present_field_names = ast_node.arguments.map(&:name)
|
103
117
|
missing_required_field_names = required_field_names - present_field_names
|
@@ -105,16 +119,19 @@ module GraphQL
|
|
105
119
|
missing_required_field_names.empty? ? @valid_response : @invalid_response
|
106
120
|
else
|
107
121
|
results = missing_required_field_names.map do |name|
|
108
|
-
arg_type = @
|
122
|
+
arg_type = @types.argument(type, name).type
|
109
123
|
recursively_validate(GraphQL::Language::Nodes::NullValue.new(name: name), arg_type)
|
110
124
|
end
|
125
|
+
if type.one_of? && ast_node.arguments.size != 1
|
126
|
+
results << Query::InputValidationResult.from_problem("`#{type.graphql_name}` is a OneOf type, so only one argument may be given (instead of #{ast_node.arguments.size})")
|
127
|
+
end
|
111
128
|
merge_results(results)
|
112
129
|
end
|
113
130
|
end
|
114
131
|
|
115
132
|
def present_input_field_values_are_valid(type, ast_node)
|
116
133
|
results = ast_node.arguments.map do |value|
|
117
|
-
field = @
|
134
|
+
field = @types.argument(type, value.name)
|
118
135
|
# we want to call validate on an argument even if it's an invalid one
|
119
136
|
# so that our raise exception is on it instead of the entire InputObject
|
120
137
|
field_type = field && field.type
|
@@ -15,7 +15,7 @@ module GraphQL
|
|
15
15
|
if @context.schema.error_bubbling || context.errors.none? { |err| err.path.take(@path.size) == @path }
|
16
16
|
parent_defn = parent_definition(parent)
|
17
17
|
|
18
|
-
if parent_defn && (arg_defn =
|
18
|
+
if parent_defn && (arg_defn = @types.argument(parent_defn, node.name))
|
19
19
|
validation_result = context.validate_literal(node.value, arg_defn.type)
|
20
20
|
if !validation_result.valid?
|
21
21
|
kind_of_node = node_type(parent)
|
@@ -16,7 +16,7 @@ module GraphQL
|
|
16
16
|
|
17
17
|
def validate_arguments(node)
|
18
18
|
argument_defns = node.arguments
|
19
|
-
if argument_defns.
|
19
|
+
if !argument_defns.empty?
|
20
20
|
args_by_name = Hash.new { |h, k| h[k] = [] }
|
21
21
|
argument_defns.each { |a| args_by_name[a.name] << a }
|
22
22
|
args_by_name.each do |name, defns|
|
@@ -5,13 +5,14 @@ module GraphQL
|
|
5
5
|
def on_argument(node, parent)
|
6
6
|
parent_defn = parent_definition(parent)
|
7
7
|
|
8
|
-
if parent_defn &&
|
8
|
+
if parent_defn && @types.argument(parent_defn, node.name)
|
9
9
|
super
|
10
10
|
elsif parent_defn
|
11
11
|
kind_of_node = node_type(parent)
|
12
12
|
error_arg_name = parent_name(parent, parent_defn)
|
13
|
+
arg_names = context.types.arguments(parent_defn).map(&:graphql_name)
|
13
14
|
add_error(GraphQL::StaticValidation::ArgumentsAreDefinedError.new(
|
14
|
-
"#{kind_of_node} '#{error_arg_name}' doesn't accept argument '#{node.name}'",
|
15
|
+
"#{kind_of_node} '#{error_arg_name}' doesn't accept argument '#{node.name}'#{context.did_you_mean_suggestion(node.name, arg_names)}",
|
15
16
|
nodes: node,
|
16
17
|
name: error_arg_name,
|
17
18
|
type: kind_of_node,
|
@@ -4,16 +4,22 @@ module GraphQL
|
|
4
4
|
module DirectivesAreDefined
|
5
5
|
def initialize(*)
|
6
6
|
super
|
7
|
-
@directive_names = context.warden.directives.map(&:graphql_name)
|
8
7
|
end
|
9
8
|
|
10
9
|
def on_directive(node, parent)
|
11
|
-
if !@
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
10
|
+
if !@types.directive_exists?(node.name)
|
11
|
+
@directives_are_defined_errors_by_name ||= {}
|
12
|
+
error = @directives_are_defined_errors_by_name[node.name] ||= begin
|
13
|
+
@directive_names ||= @types.directives.map(&:graphql_name)
|
14
|
+
err = GraphQL::StaticValidation::DirectivesAreDefinedError.new(
|
15
|
+
"Directive @#{node.name} is not defined#{context.did_you_mean_suggestion(node.name, @directive_names)}",
|
16
|
+
nodes: [],
|
17
|
+
directive: node.name
|
18
|
+
)
|
19
|
+
add_error(err)
|
20
|
+
err
|
21
|
+
end
|
22
|
+
error.nodes << node
|
17
23
|
else
|
18
24
|
super
|
19
25
|
end
|
@@ -12,20 +12,22 @@ module GraphQL
|
|
12
12
|
private
|
13
13
|
|
14
14
|
LOCATION_MESSAGE_NAMES = {
|
15
|
-
GraphQL::Directive::QUERY => "queries",
|
16
|
-
GraphQL::Directive::MUTATION => "mutations",
|
17
|
-
GraphQL::Directive::SUBSCRIPTION => "subscriptions",
|
18
|
-
GraphQL::Directive::FIELD => "fields",
|
19
|
-
GraphQL::Directive::FRAGMENT_DEFINITION => "fragment definitions",
|
20
|
-
GraphQL::Directive::FRAGMENT_SPREAD => "fragment spreads",
|
21
|
-
GraphQL::Directive::INLINE_FRAGMENT => "inline fragments",
|
15
|
+
GraphQL::Schema::Directive::QUERY => "queries",
|
16
|
+
GraphQL::Schema::Directive::MUTATION => "mutations",
|
17
|
+
GraphQL::Schema::Directive::SUBSCRIPTION => "subscriptions",
|
18
|
+
GraphQL::Schema::Directive::FIELD => "fields",
|
19
|
+
GraphQL::Schema::Directive::FRAGMENT_DEFINITION => "fragment definitions",
|
20
|
+
GraphQL::Schema::Directive::FRAGMENT_SPREAD => "fragment spreads",
|
21
|
+
GraphQL::Schema::Directive::INLINE_FRAGMENT => "inline fragments",
|
22
|
+
GraphQL::Schema::Directive::VARIABLE_DEFINITION => "variable definitions",
|
22
23
|
}
|
23
24
|
|
24
25
|
SIMPLE_LOCATIONS = {
|
25
|
-
Nodes::Field => GraphQL::Directive::FIELD,
|
26
|
-
Nodes::InlineFragment => GraphQL::Directive::INLINE_FRAGMENT,
|
27
|
-
Nodes::FragmentSpread => GraphQL::Directive::FRAGMENT_SPREAD,
|
28
|
-
Nodes::FragmentDefinition => GraphQL::Directive::FRAGMENT_DEFINITION,
|
26
|
+
Nodes::Field => GraphQL::Schema::Directive::FIELD,
|
27
|
+
Nodes::InlineFragment => GraphQL::Schema::Directive::INLINE_FRAGMENT,
|
28
|
+
Nodes::FragmentSpread => GraphQL::Schema::Directive::FRAGMENT_SPREAD,
|
29
|
+
Nodes::FragmentDefinition => GraphQL::Schema::Directive::FRAGMENT_DEFINITION,
|
30
|
+
Nodes::VariableDefinition => GraphQL::Schema::Directive::VARIABLE_DEFINITION,
|
29
31
|
}
|
30
32
|
|
31
33
|
SIMPLE_LOCATION_NODES = SIMPLE_LOCATIONS.keys
|
@@ -34,7 +36,7 @@ module GraphQL
|
|
34
36
|
directive_defn = directives[ast_directive.name]
|
35
37
|
case ast_parent
|
36
38
|
when Nodes::OperationDefinition
|
37
|
-
required_location = GraphQL::Directive.const_get(ast_parent.operation_type.upcase)
|
39
|
+
required_location = GraphQL::Schema::Directive.const_get(ast_parent.operation_type.upcase)
|
38
40
|
assert_includes_location(directive_defn, ast_directive, required_location)
|
39
41
|
when *SIMPLE_LOCATION_NODES
|
40
42
|
required_location = SIMPLE_LOCATIONS[ast_parent.class]
|
@@ -4,7 +4,7 @@ module GraphQL
|
|
4
4
|
module FieldsAreDefinedOnType
|
5
5
|
def on_field(node, parent)
|
6
6
|
parent_type = @object_types[-2]
|
7
|
-
field = context.
|
7
|
+
field = context.query.types.field(parent_type, node.name)
|
8
8
|
|
9
9
|
if field.nil?
|
10
10
|
if parent_type.kind.union?
|
@@ -14,8 +14,11 @@ module GraphQL
|
|
14
14
|
node_name: parent_type.graphql_name
|
15
15
|
))
|
16
16
|
else
|
17
|
+
possible_fields = possible_fields(context, parent_type)
|
18
|
+
suggestion = context.did_you_mean_suggestion(node.name, possible_fields)
|
19
|
+
message = "Field '#{node.name}' doesn't exist on type '#{parent_type.graphql_name}'#{suggestion}"
|
17
20
|
add_error(GraphQL::StaticValidation::FieldsAreDefinedOnTypeError.new(
|
18
|
-
|
21
|
+
message,
|
19
22
|
nodes: node,
|
20
23
|
field: node.name,
|
21
24
|
type: parent_type.graphql_name
|
@@ -25,6 +28,13 @@ module GraphQL
|
|
25
28
|
super
|
26
29
|
end
|
27
30
|
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def possible_fields(context, parent_type)
|
35
|
+
return EmptyObjects::EMPTY_ARRAY if parent_type.kind.leaf?
|
36
|
+
context.types.fields(parent_type).map(&:graphql_name)
|
37
|
+
end
|
28
38
|
end
|
29
39
|
end
|
30
40
|
end
|
@@ -25,14 +25,56 @@ module GraphQL
|
|
25
25
|
def validate_field_selections(ast_node, resolved_type)
|
26
26
|
msg = if resolved_type.nil?
|
27
27
|
nil
|
28
|
-
elsif resolved_type.kind.
|
29
|
-
if ast_node.selections.
|
30
|
-
|
28
|
+
elsif resolved_type.kind.leaf?
|
29
|
+
if !ast_node.selections.empty?
|
30
|
+
selection_strs = ast_node.selections.map do |n|
|
31
|
+
case n
|
32
|
+
when GraphQL::Language::Nodes::InlineFragment
|
33
|
+
"\"... on #{n.type.name} { ... }\""
|
34
|
+
when GraphQL::Language::Nodes::Field
|
35
|
+
"\"#{n.name}\""
|
36
|
+
when GraphQL::Language::Nodes::FragmentSpread
|
37
|
+
"\"#{n.name}\""
|
38
|
+
else
|
39
|
+
raise "Invariant: unexpected selection node: #{n}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
"Selections can't be made on #{resolved_type.kind.name.sub("_", " ").downcase}s (%{node_name} returns #{resolved_type.graphql_name} but has selections [#{selection_strs.join(", ")}])"
|
43
|
+
else
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
elsif ast_node.selections.empty?
|
47
|
+
return_validation_error = true
|
48
|
+
legacy_invalid_empty_selection_result = nil
|
49
|
+
if !resolved_type.kind.fields?
|
50
|
+
case @schema.allow_legacy_invalid_empty_selections_on_union
|
51
|
+
when true
|
52
|
+
legacy_invalid_empty_selection_result = @schema.legacy_invalid_empty_selections_on_union(@context.query)
|
53
|
+
case legacy_invalid_empty_selection_result
|
54
|
+
when :return_validation_error
|
55
|
+
# keep `return_validation_error = true`
|
56
|
+
when String
|
57
|
+
return_validation_error = false
|
58
|
+
# the string is returned below
|
59
|
+
when nil
|
60
|
+
# No error:
|
61
|
+
return_validation_error = false
|
62
|
+
legacy_invalid_empty_selection_result = nil
|
63
|
+
else
|
64
|
+
raise GraphQL::InvariantError, "Unexpected return value from legacy_invalid_empty_selections_on_union, must be `:return_validation_error`, String, or nil (got: #{legacy_invalid_empty_selection_result.inspect})"
|
65
|
+
end
|
66
|
+
when false
|
67
|
+
# pass -- error below
|
68
|
+
else
|
69
|
+
return_validation_error = false
|
70
|
+
@context.query.logger.warn("Unions require selections but #{ast_node.alias || ast_node.name} (#{resolved_type.graphql_name}) doesn't have any. This will fail with a validation error on a future GraphQL-Ruby version. More info: https://graphql-ruby.org/api-doc/#{GraphQL::VERSION}/GraphQL/Schema.html#allow_legacy_invalid_empty_selections_on_union-class_method")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
if return_validation_error
|
74
|
+
"Field must have selections (%{node_name} returns #{resolved_type.graphql_name} but has no selections. Did you mean '#{ast_node.name} { ... }'?)"
|
31
75
|
else
|
32
|
-
|
76
|
+
legacy_invalid_empty_selection_result
|
33
77
|
end
|
34
|
-
elsif resolved_type.kind.fields? && ast_node.selections.empty?
|
35
|
-
"Field must have selections (%{node_name} returns #{resolved_type.graphql_name} but has no selections. Did you mean '#{ast_node.name} { ... }'?)"
|
36
78
|
else
|
37
79
|
nil
|
38
80
|
end
|
@@ -9,7 +9,7 @@ module GraphQL
|
|
9
9
|
# without ambiguity.
|
10
10
|
#
|
11
11
|
# Original Algorithm: https://github.com/graphql/graphql-js/blob/master/src/validation/rules/OverlappingFieldsCanBeMerged.js
|
12
|
-
NO_ARGS =
|
12
|
+
NO_ARGS = GraphQL::EmptyObjects::EMPTY_HASH
|
13
13
|
|
14
14
|
Field = Struct.new(:node, :definition, :owner_type, :parents)
|
15
15
|
FragmentSpread = Struct.new(:name, :parents)
|
@@ -33,26 +33,19 @@ module GraphQL
|
|
33
33
|
|
34
34
|
private
|
35
35
|
|
36
|
-
def
|
37
|
-
@
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
def arg_conflicts
|
43
|
-
@arg_conflicts ||= Hash.new do |errors, field|
|
44
|
-
errors[field] = GraphQL::StaticValidation::FieldsWillMergeError.new(kind: :argument, field_name: field)
|
36
|
+
def conflicts
|
37
|
+
@conflicts ||= Hash.new do |h, error_type|
|
38
|
+
h[error_type] = Hash.new do |h2, field_name|
|
39
|
+
h2[field_name] = GraphQL::StaticValidation::FieldsWillMergeError.new(kind: error_type, field_name: field_name)
|
40
|
+
end
|
45
41
|
end
|
46
42
|
end
|
47
43
|
|
48
44
|
def setting_errors
|
49
|
-
@
|
50
|
-
@arg_conflicts = nil
|
51
|
-
|
45
|
+
@conflicts = nil
|
52
46
|
yield
|
53
47
|
# don't initialize these if they weren't initialized in the block:
|
54
|
-
@
|
55
|
-
@arg_conflicts && @arg_conflicts.each_value { |error| add_error(error) }
|
48
|
+
@conflicts&.each_value { |error_type| error_type.each_value { |error| add_error(error) } }
|
56
49
|
end
|
57
50
|
|
58
51
|
def conflicts_within_selection_set(node, parent_type)
|
@@ -117,8 +110,8 @@ module GraphQL
|
|
117
110
|
|
118
111
|
return if fragment1.nil? || fragment2.nil?
|
119
112
|
|
120
|
-
fragment_type1 = context.
|
121
|
-
fragment_type2 = context.
|
113
|
+
fragment_type1 = context.query.types.type(fragment1.type.name)
|
114
|
+
fragment_type2 = context.query.types.type(fragment2.type.name)
|
122
115
|
|
123
116
|
return if fragment_type1.nil? || fragment_type2.nil?
|
124
117
|
|
@@ -170,7 +163,7 @@ module GraphQL
|
|
170
163
|
fragment = context.fragments[fragment_name]
|
171
164
|
return if fragment.nil?
|
172
165
|
|
173
|
-
fragment_type =
|
166
|
+
fragment_type = @types.type(fragment.type.name)
|
174
167
|
return if fragment_type.nil?
|
175
168
|
|
176
169
|
fragment_fields, fragment_spreads = fields_and_fragments_from_selection(fragment, owner_type: fragment_type, parents: [*fragment_spread.parents, fragment_type])
|
@@ -212,6 +205,7 @@ module GraphQL
|
|
212
205
|
|
213
206
|
def find_conflict(response_key, field1, field2, mutually_exclusive: false)
|
214
207
|
return if @conflict_count >= context.max_errors
|
208
|
+
return if field1.definition.nil? || field2.definition.nil?
|
215
209
|
|
216
210
|
node1 = field1.node
|
217
211
|
node2 = field2.node
|
@@ -221,7 +215,7 @@ module GraphQL
|
|
221
215
|
|
222
216
|
if !are_mutually_exclusive
|
223
217
|
if node1.name != node2.name
|
224
|
-
conflict =
|
218
|
+
conflict = conflicts[:field][response_key]
|
225
219
|
|
226
220
|
conflict.add_conflict(node1, node1.name)
|
227
221
|
conflict.add_conflict(node2, node2.name)
|
@@ -230,7 +224,7 @@ module GraphQL
|
|
230
224
|
end
|
231
225
|
|
232
226
|
if !same_arguments?(node1, node2)
|
233
|
-
conflict =
|
227
|
+
conflict = conflicts[:argument][response_key]
|
234
228
|
|
235
229
|
conflict.add_conflict(node1, GraphQL::Language.serialize(serialize_field_args(node1)))
|
236
230
|
conflict.add_conflict(node2, GraphQL::Language.serialize(serialize_field_args(node2)))
|
@@ -239,6 +233,49 @@ module GraphQL
|
|
239
233
|
end
|
240
234
|
end
|
241
235
|
|
236
|
+
if !conflicts[:field].key?(response_key) &&
|
237
|
+
(t1 = field1.definition&.type) &&
|
238
|
+
(t2 = field2.definition&.type) &&
|
239
|
+
return_types_conflict?(t1, t2)
|
240
|
+
|
241
|
+
return_error = nil
|
242
|
+
message_override = nil
|
243
|
+
case @schema.allow_legacy_invalid_return_type_conflicts
|
244
|
+
when false
|
245
|
+
return_error = true
|
246
|
+
when true
|
247
|
+
legacy_handling = @schema.legacy_invalid_return_type_conflicts(@context.query, t1, t2, node1, node2)
|
248
|
+
case legacy_handling
|
249
|
+
when nil
|
250
|
+
return_error = false
|
251
|
+
when :return_validation_error
|
252
|
+
return_error = true
|
253
|
+
when String
|
254
|
+
return_error = true
|
255
|
+
message_override = legacy_handling
|
256
|
+
else
|
257
|
+
raise GraphQL::Error, "#{@schema}.legacy_invalid_scalar_conflicts returned unexpected value: #{legacy_handling.inspect}. Expected `nil`, String, or `:return_validation_error`."
|
258
|
+
end
|
259
|
+
else
|
260
|
+
return_error = false
|
261
|
+
@context.query.logger.warn <<~WARN
|
262
|
+
GraphQL-Ruby encountered mismatched types in this query: `#{t1.to_type_signature}` (at #{node1.line}:#{node1.col}) vs. `#{t2.to_type_signature}` (at #{node2.line}:#{node2.col}).
|
263
|
+
This will return an error in future GraphQL-Ruby versions, as per the GraphQL specification
|
264
|
+
Learn about migrating here: https://graphql-ruby.org/api-doc/#{GraphQL::VERSION}/GraphQL/Schema.html#allow_legacy_invalid_return_type_conflicts-class_method
|
265
|
+
WARN
|
266
|
+
end
|
267
|
+
|
268
|
+
if return_error
|
269
|
+
conflict = conflicts[:return_type][response_key]
|
270
|
+
if message_override
|
271
|
+
conflict.message = message_override
|
272
|
+
end
|
273
|
+
conflict.add_conflict(node1, "`#{t1.to_type_signature}`")
|
274
|
+
conflict.add_conflict(node2, "`#{t2.to_type_signature}`")
|
275
|
+
@conflict_count += 1
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
242
279
|
find_conflicts_between_sub_selection_sets(
|
243
280
|
field1,
|
244
281
|
field2,
|
@@ -246,6 +283,32 @@ module GraphQL
|
|
246
283
|
)
|
247
284
|
end
|
248
285
|
|
286
|
+
def return_types_conflict?(type1, type2)
|
287
|
+
if type1.list?
|
288
|
+
if type2.list?
|
289
|
+
return_types_conflict?(type1.of_type, type2.of_type)
|
290
|
+
else
|
291
|
+
true
|
292
|
+
end
|
293
|
+
elsif type2.list?
|
294
|
+
true
|
295
|
+
elsif type1.non_null?
|
296
|
+
if type2.non_null?
|
297
|
+
return_types_conflict?(type1.of_type, type2.of_type)
|
298
|
+
else
|
299
|
+
true
|
300
|
+
end
|
301
|
+
elsif type2.non_null?
|
302
|
+
true
|
303
|
+
elsif type1.kind.leaf? && type2.kind.leaf?
|
304
|
+
type1 != type2
|
305
|
+
else
|
306
|
+
# One or more of these are composite types,
|
307
|
+
# their selections will be validated later on.
|
308
|
+
false
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
249
312
|
def find_conflicts_between_sub_selection_sets(field1, field2, mutually_exclusive:)
|
250
313
|
return if field1.definition.nil? ||
|
251
314
|
field2.definition.nil? ||
|
@@ -323,7 +386,7 @@ module GraphQL
|
|
323
386
|
end
|
324
387
|
end
|
325
388
|
|
326
|
-
NO_SELECTIONS = [
|
389
|
+
NO_SELECTIONS = [GraphQL::EmptyObjects::EMPTY_HASH, GraphQL::EmptyObjects::EMPTY_ARRAY].freeze
|
327
390
|
|
328
391
|
def fields_and_fragments_from_selection(node, owner_type:, parents:)
|
329
392
|
if node.selections.empty?
|
@@ -340,11 +403,11 @@ module GraphQL
|
|
340
403
|
selections.each do |node|
|
341
404
|
case node
|
342
405
|
when GraphQL::Language::Nodes::Field
|
343
|
-
definition =
|
406
|
+
definition = @types.field(owner_type, node.name)
|
344
407
|
fields << Field.new(node, definition, owner_type, parents)
|
345
408
|
when GraphQL::Language::Nodes::InlineFragment
|
346
|
-
fragment_type = node.type ?
|
347
|
-
find_fields_and_fragments(node.selections, parents: [*parents, fragment_type], owner_type:
|
409
|
+
fragment_type = node.type ? @types.type(node.type.name) : owner_type
|
410
|
+
find_fields_and_fragments(node.selections, parents: [*parents, fragment_type], owner_type: fragment_type, fields: fields, fragment_spreads: fragment_spreads) if fragment_type
|
348
411
|
when GraphQL::Language::Nodes::FragmentSpread
|
349
412
|
fragment_spreads << FragmentSpread.new(node.name, parents)
|
350
413
|
end
|
@@ -396,7 +459,7 @@ module GraphQL
|
|
396
459
|
end
|
397
460
|
|
398
461
|
# Given two list of parents, find out if they are mutually exclusive
|
399
|
-
# In this context, `parents`
|
462
|
+
# In this context, `parents` represents the "self scope" of the field,
|
400
463
|
# what types may be found at this point in the query.
|
401
464
|
def mutually_exclusive?(parents1, parents2)
|
402
465
|
if parents1.empty? || parents2.empty?
|
@@ -411,8 +474,8 @@ module GraphQL
|
|
411
474
|
false
|
412
475
|
else
|
413
476
|
# Check if these two scopes have _any_ types in common.
|
414
|
-
possible_right_types = context.
|
415
|
-
possible_left_types = context.
|
477
|
+
possible_right_types = context.types.possible_types(type1)
|
478
|
+
possible_left_types = context.types.possible_types(type2)
|
416
479
|
(possible_right_types & possible_left_types).empty?
|
417
480
|
end
|
418
481
|
end
|