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
@@ -8,6 +8,7 @@ module GraphQL
|
|
8
8
|
# - Arguments, via `.argument(...)` helper, which will be applied to the field.
|
9
9
|
# - Return type, via `.type(..., null: ...)`, which will be applied to the field.
|
10
10
|
# - Description, via `.description(...)`, which will be applied to the field
|
11
|
+
# - Comment, via `.comment(...)`, which will be applied to the field
|
11
12
|
# - Resolution, via `#resolve(**args)` method, which will be called to resolve the field.
|
12
13
|
# - `#object` and `#context` accessors for use during `#resolve`.
|
13
14
|
#
|
@@ -15,18 +16,19 @@ module GraphQL
|
|
15
16
|
#
|
16
17
|
# A resolver's configuration may be overridden with other keywords in the `field(...)` call.
|
17
18
|
#
|
18
|
-
# See the {.field_options} to see how a Resolver becomes a set of field configuration options.
|
19
|
-
#
|
20
19
|
# @see {GraphQL::Schema::Mutation} for a concrete subclass of `Resolver`.
|
21
20
|
# @see {GraphQL::Function} `Resolver` is a replacement for `GraphQL::Function`
|
22
21
|
class Resolver
|
23
22
|
include Schema::Member::GraphQLTypeNames
|
24
|
-
# Really we only need description from here, but:
|
23
|
+
# Really we only need description & comment from here, but:
|
25
24
|
extend Schema::Member::BaseDSLMethods
|
26
25
|
extend GraphQL::Schema::Member::HasArguments
|
27
26
|
extend GraphQL::Schema::Member::HasValidators
|
28
27
|
include Schema::Member::HasPath
|
29
28
|
extend Schema::Member::HasPath
|
29
|
+
extend Schema::Member::HasDirectives
|
30
|
+
include Schema::Member::HasDataloader
|
31
|
+
extend Schema::Member::HasDeprecationReason
|
30
32
|
|
31
33
|
# @param object [Object] The application object that this field is being resolved on
|
32
34
|
# @param context [GraphQL::Query::Context]
|
@@ -37,7 +39,7 @@ module GraphQL
|
|
37
39
|
@field = field
|
38
40
|
# Since this hash is constantly rebuilt, cache it for this call
|
39
41
|
@arguments_by_keyword = {}
|
40
|
-
|
42
|
+
context.types.arguments(self.class).each do |arg|
|
41
43
|
@arguments_by_keyword[arg.keyword] = arg
|
42
44
|
end
|
43
45
|
@prepared_arguments = nil
|
@@ -49,11 +51,6 @@ module GraphQL
|
|
49
51
|
# @return [GraphQL::Query::Context]
|
50
52
|
attr_reader :context
|
51
53
|
|
52
|
-
# @return [GraphQL::Dataloader]
|
53
|
-
def dataloader
|
54
|
-
context.dataloader
|
55
|
-
end
|
56
|
-
|
57
54
|
# @return [GraphQL::Schema::Field]
|
58
55
|
attr_reader :field
|
59
56
|
|
@@ -67,47 +64,45 @@ module GraphQL
|
|
67
64
|
# @api private
|
68
65
|
def resolve_with_support(**args)
|
69
66
|
# First call the ready? hook which may raise
|
70
|
-
|
67
|
+
raw_ready_val = if !args.empty?
|
71
68
|
ready?(**args)
|
72
69
|
else
|
73
70
|
ready?
|
74
71
|
end
|
75
|
-
context.
|
76
|
-
if
|
72
|
+
context.query.after_lazy(raw_ready_val) do |ready_val|
|
73
|
+
if ready_val.is_a?(Array)
|
74
|
+
is_ready, ready_early_return = ready_val
|
77
75
|
if is_ready != false
|
78
|
-
raise "Unexpected result from #ready? (expected `true`, `false` or `[false, {...}]`): [#{
|
76
|
+
raise "Unexpected result from #ready? (expected `true`, `false` or `[false, {...}]`): [#{is_ready.inspect}, #{ready_early_return.inspect}]"
|
79
77
|
else
|
80
78
|
ready_early_return
|
81
79
|
end
|
82
|
-
elsif
|
80
|
+
elsif ready_val
|
83
81
|
# Then call each prepare hook, which may return a different value
|
84
82
|
# for that argument, or may return a lazy object
|
85
83
|
load_arguments_val = load_arguments(args)
|
86
|
-
context.
|
84
|
+
context.query.after_lazy(load_arguments_val) do |loaded_args|
|
87
85
|
@prepared_arguments = loaded_args
|
88
86
|
Schema::Validator.validate!(self.class.validators, object, context, loaded_args, as: @field)
|
89
87
|
# Then call `authorized?`, which may raise or may return a lazy object
|
90
|
-
|
88
|
+
raw_authorized_val = if !loaded_args.empty?
|
91
89
|
authorized?(**loaded_args)
|
92
90
|
else
|
93
91
|
authorized?
|
94
92
|
end
|
95
|
-
context.
|
93
|
+
context.query.after_lazy(raw_authorized_val) do |authorized_val|
|
96
94
|
# If the `authorized?` returned two values, `false, early_return`,
|
97
95
|
# then use the early return value instead of continuing
|
98
|
-
if
|
96
|
+
if authorized_val.is_a?(Array)
|
97
|
+
authorized_result, early_return = authorized_val
|
99
98
|
if authorized_result == false
|
100
99
|
early_return
|
101
100
|
else
|
102
101
|
raise "Unexpected result from #authorized? (expected `true`, `false` or `[false, {...}]`): [#{authorized_result.inspect}, #{early_return.inspect}]"
|
103
102
|
end
|
104
|
-
elsif
|
103
|
+
elsif authorized_val
|
105
104
|
# Finally, all the hooks have passed, so resolve it
|
106
|
-
|
107
|
-
public_send(self.class.resolve_method, **loaded_args)
|
108
|
-
else
|
109
|
-
public_send(self.class.resolve_method)
|
110
|
-
end
|
105
|
+
call_resolve(loaded_args)
|
111
106
|
else
|
112
107
|
raise GraphQL::UnauthorizedFieldError.new(context: context, object: object, type: field.owner, field: field)
|
113
108
|
end
|
@@ -117,6 +112,15 @@ module GraphQL
|
|
117
112
|
end
|
118
113
|
end
|
119
114
|
|
115
|
+
# @api private {GraphQL::Schema::Mutation} uses this to clear the dataloader cache
|
116
|
+
def call_resolve(args_hash)
|
117
|
+
if !args_hash.empty?
|
118
|
+
public_send(self.class.resolve_method, **args_hash)
|
119
|
+
else
|
120
|
+
public_send(self.class.resolve_method)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
120
124
|
# Do the work. Everything happens here.
|
121
125
|
# @return [Object] An object corresponding to the return type
|
122
126
|
def resolve(**args)
|
@@ -146,7 +150,7 @@ module GraphQL
|
|
146
150
|
# @return [Boolean, early_return_data] If `false`, execution will stop (and `early_return_data` will be returned instead, if present.)
|
147
151
|
def authorized?(**inputs)
|
148
152
|
arg_owner = @field # || self.class
|
149
|
-
args =
|
153
|
+
args = context.types.arguments(arg_owner)
|
150
154
|
authorize_arguments(args, inputs)
|
151
155
|
end
|
152
156
|
|
@@ -163,19 +167,22 @@ module GraphQL
|
|
163
167
|
private
|
164
168
|
|
165
169
|
def authorize_arguments(args, inputs)
|
166
|
-
args.
|
170
|
+
args.each do |argument|
|
167
171
|
arg_keyword = argument.keyword
|
168
172
|
if inputs.key?(arg_keyword) && !(arg_value = inputs[arg_keyword]).nil? && (arg_value != argument.default_value)
|
169
|
-
|
170
|
-
if
|
171
|
-
return
|
172
|
-
|
173
|
-
|
173
|
+
auth_result = argument.authorized?(self, arg_value, context)
|
174
|
+
if auth_result.is_a?(Array)
|
175
|
+
# only return this second value if the application returned a second value
|
176
|
+
arg_auth, err = auth_result
|
177
|
+
if !arg_auth
|
178
|
+
return arg_auth, err
|
179
|
+
end
|
180
|
+
elsif auth_result == false
|
181
|
+
return auth_result
|
174
182
|
end
|
175
|
-
else
|
176
|
-
true
|
177
183
|
end
|
178
184
|
end
|
185
|
+
true
|
179
186
|
end
|
180
187
|
|
181
188
|
def load_arguments(args)
|
@@ -187,7 +194,7 @@ module GraphQL
|
|
187
194
|
if arg_defn
|
188
195
|
prepped_value = prepared_args[key] = arg_defn.load_and_authorize_value(self, value, context)
|
189
196
|
if context.schema.lazy?(prepped_value)
|
190
|
-
prepare_lazies << context.
|
197
|
+
prepare_lazies << context.query.after_lazy(prepped_value) do |finished_prepped_value|
|
191
198
|
prepared_args[key] = finished_prepped_value
|
192
199
|
end
|
193
200
|
end
|
@@ -198,18 +205,34 @@ module GraphQL
|
|
198
205
|
end
|
199
206
|
|
200
207
|
# Avoid returning a lazy if none are needed
|
201
|
-
if prepare_lazies.
|
208
|
+
if !prepare_lazies.empty?
|
202
209
|
GraphQL::Execution::Lazy.all(prepare_lazies).then { prepared_args }
|
203
210
|
else
|
204
211
|
prepared_args
|
205
212
|
end
|
206
213
|
end
|
207
214
|
|
208
|
-
def get_argument(name, context = GraphQL::Query::NullContext)
|
215
|
+
def get_argument(name, context = GraphQL::Query::NullContext.instance)
|
209
216
|
self.class.get_argument(name, context)
|
210
217
|
end
|
211
218
|
|
212
219
|
class << self
|
220
|
+
def field_arguments(context = GraphQL::Query::NullContext.instance)
|
221
|
+
arguments(context)
|
222
|
+
end
|
223
|
+
|
224
|
+
def any_field_arguments?
|
225
|
+
any_arguments?
|
226
|
+
end
|
227
|
+
|
228
|
+
def get_field_argument(name, context = GraphQL::Query::NullContext.instance)
|
229
|
+
get_argument(name, context)
|
230
|
+
end
|
231
|
+
|
232
|
+
def all_field_argument_definitions
|
233
|
+
all_argument_definitions
|
234
|
+
end
|
235
|
+
|
213
236
|
# Default `:resolve` set below.
|
214
237
|
# @return [Symbol] The method to call on instances of this object to resolve the field
|
215
238
|
def resolve_method(new_method = nil)
|
@@ -242,6 +265,14 @@ module GraphQL
|
|
242
265
|
@null.nil? ? (superclass.respond_to?(:null) ? superclass.null : true) : @null
|
243
266
|
end
|
244
267
|
|
268
|
+
def resolver_method(new_method_name = nil)
|
269
|
+
if new_method_name
|
270
|
+
@resolver_method = new_method_name
|
271
|
+
else
|
272
|
+
@resolver_method || :resolve_with_support
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
245
276
|
# Call this method to get the return type of the field,
|
246
277
|
# or use it as a configuration method to assign a return type
|
247
278
|
# instead of generating one.
|
@@ -257,8 +288,8 @@ module GraphQL
|
|
257
288
|
@type_expr = new_type
|
258
289
|
@null = null
|
259
290
|
else
|
260
|
-
if
|
261
|
-
GraphQL::Schema::Member::BuildType.parse_type(
|
291
|
+
if type_expr
|
292
|
+
GraphQL::Schema::Member::BuildType.parse_type(type_expr, null: self.null)
|
262
293
|
elsif superclass.respond_to?(:type)
|
263
294
|
superclass.type
|
264
295
|
else
|
@@ -293,8 +324,8 @@ module GraphQL
|
|
293
324
|
# (`nil` means "unlimited max page size".)
|
294
325
|
# @param max_page_size [Integer, nil] Set a new value
|
295
326
|
# @return [Integer, nil] The `max_page_size` assigned to fields that use this resolver
|
296
|
-
def max_page_size(new_max_page_size =
|
297
|
-
if new_max_page_size !=
|
327
|
+
def max_page_size(new_max_page_size = NOT_CONFIGURED)
|
328
|
+
if new_max_page_size != NOT_CONFIGURED
|
298
329
|
@max_page_size = new_max_page_size
|
299
330
|
elsif defined?(@max_page_size)
|
300
331
|
@max_page_size
|
@@ -307,47 +338,28 @@ module GraphQL
|
|
307
338
|
|
308
339
|
# @return [Boolean] `true` if this resolver or a superclass has an assigned `max_page_size`
|
309
340
|
def has_max_page_size?
|
310
|
-
defined?(@max_page_size) || (superclass.respond_to?(:has_max_page_size?) && superclass.has_max_page_size?)
|
341
|
+
(!!defined?(@max_page_size)) || (superclass.respond_to?(:has_max_page_size?) && superclass.has_max_page_size?)
|
311
342
|
end
|
312
343
|
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
end
|
327
|
-
|
328
|
-
field_opts = {
|
329
|
-
type: type_expr,
|
330
|
-
description: description,
|
331
|
-
extras: extras,
|
332
|
-
resolver_method: :resolve_with_support,
|
333
|
-
resolver_class: self,
|
334
|
-
arguments: all_args,
|
335
|
-
null: null,
|
336
|
-
complexity: complexity,
|
337
|
-
broadcastable: broadcastable?,
|
338
|
-
}
|
339
|
-
|
340
|
-
# If there aren't any, then the returned array is `[].freeze`,
|
341
|
-
# but passing that along breaks some user code.
|
342
|
-
if (exts = extensions).any?
|
343
|
-
field_opts[:extensions] = exts
|
344
|
-
end
|
345
|
-
|
346
|
-
if has_max_page_size?
|
347
|
-
field_opts[:max_page_size] = max_page_size
|
344
|
+
# Get or set the `default_page_size:` which will be configured for fields using this resolver
|
345
|
+
# (`nil` means "unlimited default page size".)
|
346
|
+
# @param default_page_size [Integer, nil] Set a new value
|
347
|
+
# @return [Integer, nil] The `default_page_size` assigned to fields that use this resolver
|
348
|
+
def default_page_size(new_default_page_size = NOT_CONFIGURED)
|
349
|
+
if new_default_page_size != NOT_CONFIGURED
|
350
|
+
@default_page_size = new_default_page_size
|
351
|
+
elsif defined?(@default_page_size)
|
352
|
+
@default_page_size
|
353
|
+
elsif superclass.respond_to?(:default_page_size)
|
354
|
+
superclass.default_page_size
|
355
|
+
else
|
356
|
+
nil
|
348
357
|
end
|
358
|
+
end
|
349
359
|
|
350
|
-
|
360
|
+
# @return [Boolean] `true` if this resolver or a superclass has an assigned `default_page_size`
|
361
|
+
def has_default_page_size?
|
362
|
+
(!!defined?(@default_page_size)) || (superclass.respond_to?(:has_default_page_size?) && superclass.has_default_page_size?)
|
351
363
|
end
|
352
364
|
|
353
365
|
# A non-normalized type configuration, without `null` applied
|
@@ -379,7 +391,7 @@ module GraphQL
|
|
379
391
|
if superclass.respond_to?(:extensions)
|
380
392
|
s_exts = superclass.extensions
|
381
393
|
if own_exts
|
382
|
-
if s_exts.
|
394
|
+
if !s_exts.empty?
|
383
395
|
own_exts + s_exts
|
384
396
|
else
|
385
397
|
own_exts
|
@@ -392,11 +404,14 @@ module GraphQL
|
|
392
404
|
end
|
393
405
|
end
|
394
406
|
|
407
|
+
def inherited(child_class)
|
408
|
+
child_class.description(description)
|
409
|
+
super
|
410
|
+
end
|
411
|
+
|
395
412
|
private
|
396
413
|
|
397
|
-
|
398
|
-
@own_extensions
|
399
|
-
end
|
414
|
+
attr_reader :own_extensions
|
400
415
|
end
|
401
416
|
end
|
402
417
|
end
|
@@ -2,7 +2,6 @@
|
|
2
2
|
module GraphQL
|
3
3
|
class Schema
|
4
4
|
class Scalar < GraphQL::Schema::Member
|
5
|
-
extend GraphQL::Schema::Member::AcceptsDefinition
|
6
5
|
extend GraphQL::Schema::Member::ValidatesInput
|
7
6
|
|
8
7
|
class << self
|
@@ -14,29 +13,15 @@ module GraphQL
|
|
14
13
|
val
|
15
14
|
end
|
16
15
|
|
17
|
-
prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
|
18
|
-
|
19
|
-
def to_graphql
|
20
|
-
type_defn = GraphQL::ScalarType.new
|
21
|
-
type_defn.name = graphql_name
|
22
|
-
type_defn.description = description
|
23
|
-
type_defn.coerce_result = method(:coerce_result)
|
24
|
-
type_defn.coerce_input = method(:coerce_input)
|
25
|
-
type_defn.metadata[:type_class] = self
|
26
|
-
type_defn.default_scalar = default_scalar
|
27
|
-
type_defn.ast_node = ast_node
|
28
|
-
type_defn
|
29
|
-
end
|
30
|
-
|
31
16
|
def kind
|
32
17
|
GraphQL::TypeKinds::SCALAR
|
33
18
|
end
|
34
19
|
|
35
20
|
def specified_by_url(new_url = nil)
|
36
21
|
if new_url
|
37
|
-
|
38
|
-
elsif
|
39
|
-
|
22
|
+
directive(GraphQL::Schema::Directive::SpecifiedBy, url: new_url)
|
23
|
+
elsif (directive = directives.find { |dir| dir.graphql_name == "specifiedBy" })
|
24
|
+
directive.arguments[:url] # rubocop:disable Development/ContextIsPassedCop
|
40
25
|
elsif superclass.respond_to?(:specified_by_url)
|
41
26
|
superclass.specified_by_url
|
42
27
|
else
|
@@ -56,26 +41,21 @@ module GraphQL
|
|
56
41
|
end
|
57
42
|
|
58
43
|
def validate_non_null_input(value, ctx, max_errors: nil)
|
59
|
-
result = Query::InputValidationResult.new
|
60
44
|
coerced_result = begin
|
61
|
-
ctx
|
62
|
-
coerce_input(value, ctx)
|
63
|
-
end
|
45
|
+
coerce_input(value, ctx)
|
64
46
|
rescue GraphQL::CoercionError => err
|
65
47
|
err
|
48
|
+
rescue StandardError => err
|
49
|
+
ctx.query.handle_or_reraise(err)
|
66
50
|
end
|
67
51
|
|
68
52
|
if coerced_result.nil?
|
69
|
-
|
70
|
-
""
|
71
|
-
else
|
72
|
-
" #{GraphQL::Language.serialize(value)}"
|
73
|
-
end
|
74
|
-
result.add_problem("Could not coerce value#{str_value} to #{graphql_name}")
|
53
|
+
Query::InputValidationResult.from_problem("Could not coerce value #{GraphQL::Language.serialize(value)} to #{graphql_name}")
|
75
54
|
elsif coerced_result.is_a?(GraphQL::CoercionError)
|
76
|
-
|
55
|
+
Query::InputValidationResult.from_problem(coerced_result.message, message: coerced_result.message, extensions: coerced_result.extensions)
|
56
|
+
else
|
57
|
+
nil
|
77
58
|
end
|
78
|
-
result
|
79
59
|
end
|
80
60
|
end
|
81
61
|
end
|
@@ -19,29 +19,45 @@ module GraphQL
|
|
19
19
|
# propagate null.
|
20
20
|
null false
|
21
21
|
|
22
|
+
# @api private
|
22
23
|
def initialize(object:, context:, field:)
|
23
24
|
super
|
24
25
|
# Figure out whether this is an update or an initial subscription
|
25
26
|
@mode = context.query.subscription_update? ? :update : :subscribe
|
27
|
+
@subscription_written = false
|
28
|
+
@original_arguments = nil
|
29
|
+
if (subs_ns = context.namespace(:subscriptions)) &&
|
30
|
+
(sub_insts = subs_ns[:subscriptions])
|
31
|
+
sub_insts[context.current_path] = self
|
32
|
+
end
|
26
33
|
end
|
27
34
|
|
35
|
+
# @api private
|
28
36
|
def resolve_with_support(**args)
|
37
|
+
@original_arguments = args # before `loads:` have been run
|
29
38
|
result = nil
|
30
39
|
unsubscribed = true
|
31
|
-
catch :graphql_subscription_unsubscribed do
|
40
|
+
unsubscribed_result = catch :graphql_subscription_unsubscribed do
|
32
41
|
result = super
|
33
42
|
unsubscribed = false
|
34
43
|
end
|
35
44
|
|
36
45
|
|
37
46
|
if unsubscribed
|
38
|
-
|
47
|
+
if unsubscribed_result
|
48
|
+
context.namespace(:subscriptions)[:final_update] = true
|
49
|
+
unsubscribed_result
|
50
|
+
else
|
51
|
+
context.skip
|
52
|
+
end
|
39
53
|
else
|
40
54
|
result
|
41
55
|
end
|
42
56
|
end
|
43
57
|
|
44
|
-
# Implement the {Resolve} API
|
58
|
+
# Implement the {Resolve} API.
|
59
|
+
# You can implement this if you want code to run for _both_ the initial subscription
|
60
|
+
# and for later updates. Or, implement {#subscribe} and {#update}
|
45
61
|
def resolve(**args)
|
46
62
|
# Dispatch based on `@mode`, which will raise a `NoMethodError` if we ever
|
47
63
|
# have an unexpected `@mode`
|
@@ -49,8 +65,9 @@ module GraphQL
|
|
49
65
|
end
|
50
66
|
|
51
67
|
# Wrap the user-defined `#subscribe` hook
|
68
|
+
# @api private
|
52
69
|
def resolve_subscribe(**args)
|
53
|
-
ret_val = args.
|
70
|
+
ret_val = !args.empty? ? subscribe(**args) : subscribe
|
54
71
|
if ret_val == :no_response
|
55
72
|
context.skip
|
56
73
|
else
|
@@ -66,8 +83,9 @@ module GraphQL
|
|
66
83
|
end
|
67
84
|
|
68
85
|
# Wrap the user-provided `#update` hook
|
86
|
+
# @api private
|
69
87
|
def resolve_update(**args)
|
70
|
-
ret_val = args.
|
88
|
+
ret_val = !args.empty? ? update(**args) : update
|
71
89
|
if ret_val == NO_UPDATE
|
72
90
|
context.namespace(:subscriptions)[:no_update] = true
|
73
91
|
context.skip
|
@@ -94,19 +112,20 @@ module GraphQL
|
|
94
112
|
end
|
95
113
|
|
96
114
|
# Call this to halt execution and remove this subscription from the system
|
97
|
-
|
115
|
+
# @param update_value [Object] if present, deliver this update before unsubscribing
|
116
|
+
# @return [void]
|
117
|
+
def unsubscribe(update_value = nil)
|
98
118
|
context.namespace(:subscriptions)[:unsubscribed] = true
|
99
|
-
throw :graphql_subscription_unsubscribed
|
119
|
+
throw :graphql_subscription_unsubscribed, update_value
|
100
120
|
end
|
101
121
|
|
102
|
-
READING_SCOPE = ::Object.new
|
103
122
|
# Call this method to provide a new subscription_scope; OR
|
104
123
|
# call it without an argument to get the subscription_scope
|
105
124
|
# @param new_scope [Symbol]
|
106
125
|
# @param optional [Boolean] If true, then don't require `scope:` to be provided to updates to this subscription.
|
107
126
|
# @return [Symbol]
|
108
|
-
def self.subscription_scope(new_scope =
|
109
|
-
if new_scope !=
|
127
|
+
def self.subscription_scope(new_scope = NOT_CONFIGURED, optional: false)
|
128
|
+
if new_scope != NOT_CONFIGURED
|
110
129
|
@subscription_scope = new_scope
|
111
130
|
@subscription_scope_optional = optional
|
112
131
|
elsif defined?(@subscription_scope)
|
@@ -144,10 +163,37 @@ module GraphQL
|
|
144
163
|
Subscriptions::Serialize.dump_recursive([scope, field.graphql_name, arguments])
|
145
164
|
end
|
146
165
|
|
147
|
-
#
|
148
|
-
|
149
|
-
|
150
|
-
|
166
|
+
# Calls through to `schema.subscriptions` to register this subscription with the backend.
|
167
|
+
# This is automatically called by GraphQL-Ruby after a query finishes successfully,
|
168
|
+
# but if you need to commit the subscription during `#subscribe`, you can call it there.
|
169
|
+
# (This method also sets a flag showing that this subscription was already written.)
|
170
|
+
#
|
171
|
+
# If you call this method yourself, you may also need to {#unsubscribe}
|
172
|
+
# or call `subscriptions.delete_subscription` to clean up the database if the query crashes with an error
|
173
|
+
# later in execution.
|
174
|
+
# @return [void]
|
175
|
+
def write_subscription
|
176
|
+
if subscription_written?
|
177
|
+
raise GraphQL::Error, "`write_subscription` was called but `#{self.class}#subscription_written?` is already true. Remove a call to `write subscription`."
|
178
|
+
else
|
179
|
+
@subscription_written = true
|
180
|
+
context.schema.subscriptions.write_subscription(context.query, [event])
|
181
|
+
end
|
182
|
+
nil
|
183
|
+
end
|
184
|
+
|
185
|
+
# @return [Boolean] `true` if {#write_subscription} was called already
|
186
|
+
def subscription_written?
|
187
|
+
@subscription_written
|
188
|
+
end
|
189
|
+
|
190
|
+
# @return [Subscriptions::Event] This object is used as a representation of this subscription for the backend
|
191
|
+
def event
|
192
|
+
@event ||= Subscriptions::Event.new(
|
193
|
+
name: field.name,
|
194
|
+
arguments: @original_arguments,
|
195
|
+
context: context,
|
196
|
+
field: field,
|
151
197
|
)
|
152
198
|
end
|
153
199
|
end
|
@@ -33,60 +33,64 @@ module GraphQL
|
|
33
33
|
# end
|
34
34
|
#
|
35
35
|
class Timeout
|
36
|
-
def self.use(schema,
|
37
|
-
|
38
|
-
schema.
|
36
|
+
def self.use(schema, max_seconds: nil)
|
37
|
+
timeout = self.new(max_seconds: max_seconds)
|
38
|
+
schema.trace_with(self::Trace, timeout: timeout)
|
39
39
|
end
|
40
40
|
|
41
|
-
# @param max_seconds [Numeric] how many seconds the query should be allowed to resolve new fields
|
42
41
|
def initialize(max_seconds:)
|
43
42
|
@max_seconds = max_seconds
|
44
43
|
end
|
45
44
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
45
|
+
module Trace
|
46
|
+
# @param max_seconds [Numeric] how many seconds the query should be allowed to resolve new fields
|
47
|
+
def initialize(timeout:, **rest)
|
48
|
+
@timeout = timeout
|
49
|
+
super
|
50
|
+
end
|
51
|
+
|
52
|
+
def execute_multiplex(multiplex:)
|
53
|
+
multiplex.queries.each do |query|
|
54
|
+
timeout_duration_s = @timeout.max_seconds(query)
|
51
55
|
timeout_state = if timeout_duration_s == false
|
52
56
|
# if the method returns `false`, don't apply a timeout
|
53
57
|
false
|
54
58
|
else
|
55
59
|
now = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
|
56
|
-
timeout_at = now + (
|
60
|
+
timeout_at = now + (timeout_duration_s * 1000)
|
57
61
|
{
|
58
62
|
timeout_at: timeout_at,
|
59
63
|
timed_out: false
|
60
64
|
}
|
61
65
|
end
|
62
|
-
query.context.namespace(
|
66
|
+
query.context.namespace(@timeout)[:state] = timeout_state
|
63
67
|
end
|
68
|
+
super
|
69
|
+
end
|
64
70
|
|
65
|
-
|
66
|
-
|
67
|
-
query_context = data[:context] || data[:query].context
|
68
|
-
timeout_state = query_context.namespace(self.class).fetch(:state)
|
71
|
+
def execute_field(query:, field:, **_rest)
|
72
|
+
timeout_state = query.context.namespace(@timeout).fetch(:state)
|
69
73
|
# If the `:state` is `false`, then `max_seconds(query)` opted out of timeout for this query.
|
70
|
-
if timeout_state
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
field = data.fetch(:field)
|
75
|
-
GraphQL::Schema::Timeout::TimeoutError.new(field.owner, field)
|
76
|
-
end
|
77
|
-
|
74
|
+
if timeout_state == false
|
75
|
+
super
|
76
|
+
elsif Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond) > timeout_state.fetch(:timeout_at)
|
77
|
+
error = GraphQL::Schema::Timeout::TimeoutError.new(field)
|
78
78
|
# Only invoke the timeout callback for the first timeout
|
79
79
|
if !timeout_state[:timed_out]
|
80
80
|
timeout_state[:timed_out] = true
|
81
|
-
handle_timeout(error,
|
81
|
+
@timeout.handle_timeout(error, query)
|
82
|
+
timeout_state = query.context.namespace(@timeout).fetch(:state)
|
82
83
|
end
|
83
84
|
|
84
|
-
|
85
|
+
# `handle_timeout` may have set this to be `false`
|
86
|
+
if timeout_state != false
|
87
|
+
error
|
88
|
+
else
|
89
|
+
super
|
90
|
+
end
|
85
91
|
else
|
86
|
-
|
92
|
+
super
|
87
93
|
end
|
88
|
-
else
|
89
|
-
yield
|
90
94
|
end
|
91
95
|
end
|
92
96
|
|
@@ -94,7 +98,7 @@ module GraphQL
|
|
94
98
|
# The default implementation returns the `max_seconds:` value from installing this plugin.
|
95
99
|
#
|
96
100
|
# @param query [GraphQL::Query] The query that's about to run
|
97
|
-
# @return [
|
101
|
+
# @return [Numeric, false] The number of seconds after which to interrupt query execution and call {#handle_error}, or `false` to bypass the timeout.
|
98
102
|
def max_seconds(query)
|
99
103
|
@max_seconds
|
100
104
|
end
|
@@ -106,6 +110,15 @@ module GraphQL
|
|
106
110
|
# override to do something interesting
|
107
111
|
end
|
108
112
|
|
113
|
+
# Call this method (eg, from {#handle_timeout}) to disable timeout tracking
|
114
|
+
# for the given query.
|
115
|
+
# @param query [GraphQL::Query]
|
116
|
+
# @return [void]
|
117
|
+
def disable_timeout(query)
|
118
|
+
query.context.namespace(self)[:state] = false
|
119
|
+
nil
|
120
|
+
end
|
121
|
+
|
109
122
|
# This error is raised when a query exceeds `max_seconds`.
|
110
123
|
# Since it's a child of {GraphQL::ExecutionError},
|
111
124
|
# its message will be added to the response's `errors` key.
|
@@ -114,8 +127,8 @@ module GraphQL
|
|
114
127
|
# to take this error and raise a new one which _doesn't_ descend from {GraphQL::ExecutionError},
|
115
128
|
# such as `RuntimeError`.
|
116
129
|
class TimeoutError < GraphQL::ExecutionError
|
117
|
-
def initialize(
|
118
|
-
super("Timeout on #{
|
130
|
+
def initialize(field)
|
131
|
+
super("Timeout on #{field.path}")
|
119
132
|
end
|
120
133
|
end
|
121
134
|
end
|