graphql 1.9.21 → 2.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of graphql might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/generators/graphql/core.rb +21 -10
- data/lib/generators/graphql/enum_generator.rb +4 -10
- data/lib/generators/graphql/field_extractor.rb +31 -0
- data/lib/generators/graphql/input_generator.rb +50 -0
- data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
- data/lib/generators/graphql/{templates → install/templates}/base_mutation.erb +2 -0
- data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +2 -0
- data/lib/generators/graphql/install_generator.rb +45 -8
- data/lib/generators/graphql/interface_generator.rb +7 -7
- data/lib/generators/graphql/loader_generator.rb +1 -0
- data/lib/generators/graphql/mutation_create_generator.rb +22 -0
- data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
- data/lib/generators/graphql/mutation_generator.rb +6 -30
- data/lib/generators/graphql/mutation_update_generator.rb +22 -0
- data/lib/generators/graphql/object_generator.rb +28 -12
- data/lib/generators/graphql/orm_mutations_base.rb +40 -0
- data/lib/generators/graphql/relay.rb +49 -0
- data/lib/generators/graphql/relay_generator.rb +21 -0
- data/lib/generators/graphql/scalar_generator.rb +4 -2
- data/lib/generators/graphql/templates/base_argument.erb +2 -0
- data/lib/generators/graphql/templates/base_connection.erb +8 -0
- data/lib/generators/graphql/templates/base_edge.erb +8 -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_scalar.erb +2 -0
- data/lib/generators/graphql/templates/base_union.erb +2 -0
- data/lib/generators/graphql/templates/enum.erb +7 -1
- data/lib/generators/graphql/templates/graphql_controller.erb +16 -12
- data/lib/generators/graphql/templates/input.erb +9 -0
- data/lib/generators/graphql/templates/interface.erb +6 -2
- data/lib/generators/graphql/templates/loader.erb +2 -0
- data/lib/generators/graphql/templates/mutation.erb +3 -1
- data/lib/generators/graphql/templates/mutation_create.erb +20 -0
- data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
- data/lib/generators/graphql/templates/mutation_update.erb +21 -0
- data/lib/generators/graphql/templates/node_type.erb +9 -0
- data/lib/generators/graphql/templates/object.erb +7 -3
- data/lib/generators/graphql/templates/query_type.erb +3 -3
- data/lib/generators/graphql/templates/scalar.erb +5 -1
- data/lib/generators/graphql/templates/schema.erb +25 -27
- data/lib/generators/graphql/templates/union.erb +6 -2
- data/lib/generators/graphql/type_generator.rb +47 -10
- data/lib/generators/graphql/union_generator.rb +5 -5
- data/lib/graphql/analysis/ast/field_usage.rb +31 -2
- data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -1
- data/lib/graphql/analysis/ast/query_complexity.rb +175 -68
- data/lib/graphql/analysis/ast/query_depth.rb +0 -1
- data/lib/graphql/analysis/ast/visitor.rb +17 -8
- data/lib/graphql/analysis/ast.rb +14 -14
- data/lib/graphql/analysis.rb +0 -7
- data/lib/graphql/backtrace/inspect_result.rb +0 -1
- data/lib/graphql/backtrace/table.rb +37 -16
- data/lib/graphql/backtrace/traced_error.rb +0 -1
- data/lib/graphql/backtrace/tracer.rb +39 -9
- data/lib/graphql/backtrace.rb +20 -17
- data/lib/graphql/dataloader/null_dataloader.rb +24 -0
- data/lib/graphql/dataloader/request.rb +19 -0
- data/lib/graphql/dataloader/request_all.rb +19 -0
- data/lib/graphql/dataloader/source.rb +164 -0
- data/lib/graphql/dataloader.rb +311 -0
- data/lib/graphql/date_encoding_error.rb +16 -0
- data/lib/graphql/deprecation.rb +9 -0
- data/lib/graphql/dig.rb +1 -1
- data/lib/graphql/execution/directive_checks.rb +2 -2
- data/lib/graphql/execution/errors.rb +77 -45
- data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
- data/lib/graphql/execution/interpreter/arguments.rb +88 -0
- data/lib/graphql/execution/interpreter/arguments_cache.rb +105 -0
- data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
- data/lib/graphql/execution/interpreter/resolve.rb +44 -25
- data/lib/graphql/execution/interpreter/runtime.rb +755 -395
- data/lib/graphql/execution/interpreter.rb +201 -74
- data/lib/graphql/execution/lazy/lazy_method_map.rb +4 -0
- data/lib/graphql/execution/lazy.rb +5 -9
- data/lib/graphql/execution/lookahead.rb +65 -136
- data/lib/graphql/execution/multiplex.rb +5 -152
- data/lib/graphql/execution.rb +11 -4
- data/lib/graphql/filter.rb +1 -1
- data/lib/graphql/integer_decoding_error.rb +17 -0
- data/lib/graphql/integer_encoding_error.rb +18 -2
- data/lib/graphql/introspection/base_object.rb +2 -5
- data/lib/graphql/introspection/directive_location_enum.rb +2 -2
- data/lib/graphql/introspection/directive_type.rb +11 -5
- data/lib/graphql/introspection/dynamic_fields.rb +3 -8
- data/lib/graphql/introspection/entry_points.rb +5 -18
- data/lib/graphql/introspection/enum_value_type.rb +2 -2
- data/lib/graphql/introspection/field_type.rb +9 -5
- data/lib/graphql/introspection/input_value_type.rb +41 -11
- data/lib/graphql/introspection/introspection_query.rb +6 -92
- data/lib/graphql/introspection/schema_type.rb +10 -10
- data/lib/graphql/introspection/type_type.rb +34 -17
- data/lib/graphql/introspection.rb +100 -0
- data/lib/graphql/invalid_null_error.rb +18 -0
- data/lib/graphql/language/block_string.rb +20 -5
- data/lib/graphql/language/cache.rb +37 -0
- data/lib/graphql/language/definition_slice.rb +21 -10
- data/lib/graphql/language/document_from_schema_definition.rb +104 -68
- data/lib/graphql/language/lexer.rb +83 -40
- data/lib/graphql/language/lexer.rl +31 -9
- data/lib/graphql/language/nodes.rb +64 -93
- data/lib/graphql/language/parser.rb +940 -896
- data/lib/graphql/language/parser.y +130 -103
- data/lib/graphql/language/printer.rb +48 -23
- data/lib/graphql/language/sanitized_printer.rb +222 -0
- data/lib/graphql/language/token.rb +0 -4
- data/lib/graphql/language/visitor.rb +2 -2
- data/lib/graphql/language.rb +3 -1
- data/lib/graphql/name_validator.rb +2 -7
- data/lib/graphql/pagination/active_record_relation_connection.rb +85 -0
- data/lib/graphql/pagination/array_connection.rb +79 -0
- data/lib/graphql/pagination/connection.rb +253 -0
- data/lib/graphql/pagination/connections.rb +135 -0
- data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
- data/lib/graphql/pagination/relation_connection.rb +228 -0
- data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
- data/lib/graphql/pagination.rb +6 -0
- data/lib/graphql/parse_error.rb +0 -1
- data/lib/graphql/query/context.rb +172 -198
- data/lib/graphql/query/fingerprint.rb +26 -0
- data/lib/graphql/query/input_validation_result.rb +33 -7
- data/lib/graphql/query/null_context.rb +21 -8
- data/lib/graphql/query/validation_pipeline.rb +16 -38
- data/lib/graphql/query/variable_validation_error.rb +3 -3
- data/lib/graphql/query/variables.rb +39 -12
- data/lib/graphql/query.rb +74 -38
- data/lib/graphql/railtie.rb +6 -102
- data/lib/graphql/rake_task/validate.rb +4 -1
- data/lib/graphql/rake_task.rb +41 -10
- data/lib/graphql/relay/range_add.rb +17 -10
- data/lib/graphql/relay.rb +0 -15
- data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
- data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
- data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
- data/lib/graphql/rubocop.rb +4 -0
- data/lib/graphql/schema/addition.rb +245 -0
- data/lib/graphql/schema/argument.rb +286 -31
- data/lib/graphql/schema/base_64_encoder.rb +2 -0
- data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +1 -1
- data/lib/graphql/schema/build_from_definition/resolve_map.rb +13 -5
- data/lib/graphql/schema/build_from_definition.rb +334 -220
- data/lib/graphql/schema/built_in_types.rb +5 -5
- data/lib/graphql/schema/directive/deprecated.rb +18 -0
- data/lib/graphql/schema/directive/feature.rb +1 -1
- data/lib/graphql/schema/directive/flagged.rb +57 -0
- data/lib/graphql/schema/directive/include.rb +2 -2
- data/lib/graphql/schema/directive/one_of.rb +12 -0
- data/lib/graphql/schema/directive/skip.rb +2 -2
- data/lib/graphql/schema/directive/transform.rb +14 -2
- data/lib/graphql/schema/directive.rb +117 -14
- data/lib/graphql/schema/enum.rb +113 -22
- data/lib/graphql/schema/enum_value.rb +16 -21
- data/lib/graphql/schema/field/connection_extension.rb +50 -20
- data/lib/graphql/schema/field/scope_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +491 -329
- data/lib/graphql/schema/field_extension.rb +89 -2
- data/lib/graphql/schema/find_inherited_value.rb +17 -1
- data/lib/graphql/schema/finder.rb +16 -14
- data/lib/graphql/schema/input_object.rb +182 -60
- data/lib/graphql/schema/interface.rb +28 -43
- data/lib/graphql/schema/introspection_system.rb +101 -38
- data/lib/graphql/schema/late_bound_type.rb +7 -2
- data/lib/graphql/schema/list.rb +61 -3
- data/lib/graphql/schema/loader.rb +144 -102
- data/lib/graphql/schema/member/base_dsl_methods.rb +33 -32
- data/lib/graphql/schema/member/build_type.rb +24 -15
- data/lib/graphql/schema/member/has_arguments.rb +261 -24
- data/lib/graphql/schema/member/has_ast_node.rb +20 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
- data/lib/graphql/schema/member/has_directives.rb +113 -0
- data/lib/graphql/schema/member/has_fields.rb +99 -34
- data/lib/graphql/schema/member/has_interfaces.rb +88 -0
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
- data/lib/graphql/schema/member/has_validators.rb +31 -0
- data/lib/graphql/schema/member/relay_shortcuts.rb +28 -2
- data/lib/graphql/schema/member/type_system_helpers.rb +3 -3
- data/lib/graphql/schema/member/validates_input.rb +33 -0
- data/lib/graphql/schema/member.rb +11 -6
- data/lib/graphql/schema/mutation.rb +4 -9
- data/lib/graphql/schema/non_null.rb +34 -4
- data/lib/graphql/schema/object.rb +38 -60
- data/lib/graphql/schema/printer.rb +16 -35
- data/lib/graphql/schema/relay_classic_mutation.rb +90 -43
- data/lib/graphql/schema/resolver/has_payload_type.rb +46 -6
- data/lib/graphql/schema/resolver.rb +146 -93
- data/lib/graphql/schema/scalar.rb +40 -15
- data/lib/graphql/schema/subscription.rb +55 -26
- data/lib/graphql/schema/timeout.rb +29 -15
- data/lib/graphql/schema/type_expression.rb +21 -13
- data/lib/graphql/schema/type_membership.rb +22 -5
- data/lib/graphql/schema/union.rb +48 -14
- data/lib/graphql/schema/unique_within_type.rb +1 -2
- data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
- data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
- data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
- data/lib/graphql/schema/validator/format_validator.rb +48 -0
- data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
- data/lib/graphql/schema/validator/length_validator.rb +59 -0
- data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
- data/lib/graphql/schema/validator/required_validator.rb +82 -0
- data/lib/graphql/schema/validator.rb +171 -0
- data/lib/graphql/schema/warden.rb +187 -33
- data/lib/graphql/schema/wrapper.rb +0 -5
- data/lib/graphql/schema.rb +773 -892
- data/lib/graphql/static_validation/all_rules.rb +3 -0
- data/lib/graphql/static_validation/base_visitor.rb +21 -31
- data/lib/graphql/static_validation/definition_dependencies.rb +7 -2
- data/lib/graphql/static_validation/error.rb +3 -1
- data/lib/graphql/static_validation/literal_validator.rb +55 -26
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +45 -83
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +22 -6
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +35 -26
- data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +12 -6
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +14 -14
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +4 -4
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +5 -5
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +94 -51
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
- data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
- data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -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 +17 -0
- data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -2
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +9 -10
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +13 -7
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +12 -13
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +19 -14
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +5 -3
- data/lib/graphql/static_validation/type_stack.rb +2 -2
- data/lib/graphql/static_validation/validation_context.rb +13 -3
- data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
- data/lib/graphql/static_validation/validator.rb +31 -19
- data/lib/graphql/static_validation.rb +1 -2
- data/lib/graphql/string_encoding_error.rb +13 -3
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +129 -22
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +58 -0
- data/lib/graphql/subscriptions/event.rb +85 -31
- data/lib/graphql/subscriptions/instrumentation.rb +0 -47
- data/lib/graphql/subscriptions/serialize.rb +53 -6
- data/lib/graphql/subscriptions.rb +137 -57
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +8 -17
- data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
- data/lib/graphql/tracing/appsignal_tracing.rb +23 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +34 -2
- data/lib/graphql/tracing/new_relic_tracing.rb +9 -12
- data/lib/graphql/tracing/notifications_tracing.rb +59 -0
- data/lib/graphql/tracing/platform_tracing.rb +67 -38
- data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
- data/lib/graphql/tracing/prometheus_tracing.rb +8 -0
- data/lib/graphql/tracing/scout_tracing.rb +19 -0
- data/lib/graphql/tracing/statsd_tracing.rb +42 -0
- data/lib/graphql/tracing.rb +15 -36
- data/lib/graphql/types/big_int.rb +5 -1
- data/lib/graphql/types/int.rb +10 -3
- data/lib/graphql/types/iso_8601_date.rb +20 -9
- data/lib/graphql/types/iso_8601_date_time.rb +36 -10
- data/lib/graphql/types/relay/base_connection.rb +18 -90
- data/lib/graphql/types/relay/base_edge.rb +2 -34
- data/lib/graphql/types/relay/connection_behaviors.rb +158 -0
- data/lib/graphql/types/relay/default_relay.rb +27 -0
- data/lib/graphql/types/relay/edge_behaviors.rb +65 -0
- data/lib/graphql/types/relay/has_node_field.rb +41 -0
- data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
- data/lib/graphql/types/relay/node.rb +2 -4
- data/lib/graphql/types/relay/node_behaviors.rb +19 -0
- data/lib/graphql/types/relay/page_info.rb +2 -14
- data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
- data/lib/graphql/types/relay.rb +11 -5
- data/lib/graphql/types/string.rb +8 -2
- data/lib/graphql/unauthorized_error.rb +2 -2
- data/lib/graphql/unresolved_type_error.rb +2 -2
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +41 -58
- data/readme.md +3 -6
- metadata +103 -237
- data/lib/graphql/analysis/analyze_query.rb +0 -91
- data/lib/graphql/analysis/field_usage.rb +0 -45
- data/lib/graphql/analysis/max_query_complexity.rb +0 -26
- data/lib/graphql/analysis/max_query_depth.rb +0 -26
- data/lib/graphql/analysis/query_complexity.rb +0 -88
- data/lib/graphql/analysis/query_depth.rb +0 -43
- data/lib/graphql/analysis/reducer_state.rb +0 -48
- data/lib/graphql/argument.rb +0 -159
- data/lib/graphql/authorization.rb +0 -82
- data/lib/graphql/backwards_compatibility.rb +0 -60
- data/lib/graphql/base_type.rb +0 -226
- 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 -435
- data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
- data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -213
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -91
- data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
- data/lib/graphql/compatibility/query_parser_specification.rb +0 -264
- data/lib/graphql/compatibility/schema_parser_specification.rb +0 -680
- 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 -311
- 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 -42
- data/lib/graphql/directive/deprecated_directive.rb +0 -13
- data/lib/graphql/directive/include_directive.rb +0 -2
- data/lib/graphql/directive/skip_directive.rb +0 -2
- data/lib/graphql/directive.rb +0 -104
- data/lib/graphql/enum_type.rb +0 -193
- data/lib/graphql/execution/execute.rb +0 -326
- data/lib/graphql/execution/flatten.rb +0 -40
- data/lib/graphql/execution/instrumentation.rb +0 -92
- data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
- 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 -330
- data/lib/graphql/float_type.rb +0 -2
- data/lib/graphql/function.rb +0 -153
- data/lib/graphql/id_type.rb +0 -2
- data/lib/graphql/input_object_type.rb +0 -154
- data/lib/graphql/int_type.rb +0 -2
- data/lib/graphql/interface_type.rb +0 -86
- 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/list_type.rb +0 -80
- data/lib/graphql/literal_validation_error.rb +0 -6
- data/lib/graphql/non_null_type.rb +0 -81
- data/lib/graphql/object_type.rb +0 -141
- data/lib/graphql/query/arguments.rb +0 -187
- data/lib/graphql/query/arguments_cache.rb +0 -25
- data/lib/graphql/query/executor.rb +0 -53
- data/lib/graphql/query/literal_input.rb +0 -116
- 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 -39
- data/lib/graphql/relay/array_connection.rb +0 -85
- data/lib/graphql/relay/base_connection.rb +0 -172
- 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 -40
- data/lib/graphql/relay/edge.rb +0 -27
- data/lib/graphql/relay/edge_type.rb +0 -18
- data/lib/graphql/relay/edges_instrumentation.rb +0 -40
- data/lib/graphql/relay/global_id_resolve.rb +0 -18
- data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
- data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
- data/lib/graphql/relay/mutation/resolve.rb +0 -56
- data/lib/graphql/relay/mutation/result.rb +0 -38
- data/lib/graphql/relay/mutation.rb +0 -190
- data/lib/graphql/relay/node.rb +0 -36
- data/lib/graphql/relay/page_info.rb +0 -7
- data/lib/graphql/relay/relation_connection.rb +0 -190
- data/lib/graphql/relay/type_extensions.rb +0 -30
- data/lib/graphql/scalar_type.rb +0 -133
- 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 -15
- data/lib/graphql/schema/member/accepts_definition.rb +0 -152
- data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -26
- data/lib/graphql/schema/member/instrumentation.rb +0 -132
- data/lib/graphql/schema/middleware_chain.rb +0 -82
- data/lib/graphql/schema/possible_types.rb +0 -39
- data/lib/graphql/schema/rescue_middleware.rb +0 -60
- data/lib/graphql/schema/timeout_middleware.rb +0 -86
- data/lib/graphql/schema/traversal.rb +0 -228
- data/lib/graphql/schema/validation.rb +0 -303
- data/lib/graphql/static_validation/default_visitor.rb +0 -15
- data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
- data/lib/graphql/string_type.rb +0 -2
- data/lib/graphql/subscriptions/subscription_root.rb +0 -74
- data/lib/graphql/tracing/skylight_tracing.rb +0 -62
- data/lib/graphql/types/relay/base_field.rb +0 -22
- data/lib/graphql/types/relay/base_interface.rb +0 -29
- data/lib/graphql/types/relay/base_object.rb +0 -26
- data/lib/graphql/types/relay/node_field.rb +0 -43
- data/lib/graphql/types/relay/nodes_field.rb +0 -45
- data/lib/graphql/union_type.rb +0 -135
- data/lib/graphql/upgrader/member.rb +0 -936
- data/lib/graphql/upgrader/schema.rb +0 -37
@@ -15,8 +15,6 @@ module GraphQL
|
|
15
15
|
#
|
16
16
|
# A resolver's configuration may be overridden with other keywords in the `field(...)` call.
|
17
17
|
#
|
18
|
-
# See the {.field_options} to see how a Resolver becomes a set of field configuration options.
|
19
|
-
#
|
20
18
|
# @see {GraphQL::Schema::Mutation} for a concrete subclass of `Resolver`.
|
21
19
|
# @see {GraphQL::Function} `Resolver` is a replacement for `GraphQL::Function`
|
22
20
|
class Resolver
|
@@ -24,10 +22,11 @@ module GraphQL
|
|
24
22
|
# Really we only need description from here, but:
|
25
23
|
extend Schema::Member::BaseDSLMethods
|
26
24
|
extend GraphQL::Schema::Member::HasArguments
|
25
|
+
extend GraphQL::Schema::Member::HasValidators
|
27
26
|
include Schema::Member::HasPath
|
28
27
|
extend Schema::Member::HasPath
|
29
28
|
|
30
|
-
# @param object [Object]
|
29
|
+
# @param object [Object] The application object that this field is being resolved on
|
31
30
|
# @param context [GraphQL::Query::Context]
|
32
31
|
# @param field [GraphQL::Schema::Field]
|
33
32
|
def initialize(object:, context:, field:)
|
@@ -36,10 +35,10 @@ module GraphQL
|
|
36
35
|
@field = field
|
37
36
|
# Since this hash is constantly rebuilt, cache it for this call
|
38
37
|
@arguments_by_keyword = {}
|
39
|
-
self.class.arguments.each do |name, arg|
|
38
|
+
self.class.arguments(context).each do |name, arg|
|
40
39
|
@arguments_by_keyword[arg.keyword] = arg
|
41
40
|
end
|
42
|
-
@
|
41
|
+
@prepared_arguments = nil
|
43
42
|
end
|
44
43
|
|
45
44
|
# @return [Object] The application object this field is being resolved on
|
@@ -48,9 +47,18 @@ module GraphQL
|
|
48
47
|
# @return [GraphQL::Query::Context]
|
49
48
|
attr_reader :context
|
50
49
|
|
50
|
+
# @return [GraphQL::Dataloader]
|
51
|
+
def dataloader
|
52
|
+
context.dataloader
|
53
|
+
end
|
54
|
+
|
51
55
|
# @return [GraphQL::Schema::Field]
|
52
56
|
attr_reader :field
|
53
57
|
|
58
|
+
def arguments
|
59
|
+
@prepared_arguments || raise("Arguments have not been prepared yet, still waiting for #load_arguments to resolve. (Call `.arguments` later in the code.)")
|
60
|
+
end
|
61
|
+
|
54
62
|
# This method is _actually_ called by the runtime,
|
55
63
|
# it does some preparation and then eventually calls
|
56
64
|
# the user-defined `#resolve` method.
|
@@ -65,7 +73,7 @@ module GraphQL
|
|
65
73
|
context.schema.after_lazy(ready_val) do |is_ready, ready_early_return|
|
66
74
|
if ready_early_return
|
67
75
|
if is_ready != false
|
68
|
-
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}]"
|
69
77
|
else
|
70
78
|
ready_early_return
|
71
79
|
end
|
@@ -74,6 +82,8 @@ module GraphQL
|
|
74
82
|
# for that argument, or may return a lazy object
|
75
83
|
load_arguments_val = load_arguments(args)
|
76
84
|
context.schema.after_lazy(load_arguments_val) do |loaded_args|
|
85
|
+
@prepared_arguments = loaded_args
|
86
|
+
Schema::Validator.validate!(self.class.validators, object, context, loaded_args, as: @field)
|
77
87
|
# Then call `authorized?`, which may raise or may return a lazy object
|
78
88
|
authorized_val = if loaded_args.any?
|
79
89
|
authorized?(**loaded_args)
|
@@ -97,7 +107,7 @@ module GraphQL
|
|
97
107
|
public_send(self.class.resolve_method)
|
98
108
|
end
|
99
109
|
else
|
100
|
-
|
110
|
+
raise GraphQL::UnauthorizedFieldError.new(context: context, object: object, type: field.owner, field: field)
|
101
111
|
end
|
102
112
|
end
|
103
113
|
end
|
@@ -133,22 +143,28 @@ module GraphQL
|
|
133
143
|
# @raise [GraphQL::UnauthorizedError] To signal an authorization failure
|
134
144
|
# @return [Boolean, early_return_data] If `false`, execution will stop (and `early_return_data` will be returned instead, if present.)
|
135
145
|
def authorized?(**inputs)
|
136
|
-
self.class
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
146
|
+
arg_owner = @field # || self.class
|
147
|
+
args = arg_owner.arguments(context)
|
148
|
+
authorize_arguments(args, inputs)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Called when an object loaded by `loads:` fails the `.authorized?` check for its resolved GraphQL object type.
|
152
|
+
#
|
153
|
+
# By default, the error is re-raised and passed along to {{Schema.unauthorized_object}}.
|
154
|
+
#
|
155
|
+
# Any value returned here will be used _instead of_ of the loaded object.
|
156
|
+
# @param err [GraphQL::UnauthorizedError]
|
157
|
+
def unauthorized_object(err)
|
158
|
+
raise err
|
159
|
+
end
|
160
|
+
|
161
|
+
private
|
150
162
|
|
151
|
-
|
163
|
+
def authorize_arguments(args, inputs)
|
164
|
+
args.each_value do |argument|
|
165
|
+
arg_keyword = argument.keyword
|
166
|
+
if inputs.key?(arg_keyword) && !(arg_value = inputs[arg_keyword]).nil? && (arg_value != argument.default_value)
|
167
|
+
arg_auth, err = argument.authorized?(self, arg_value, context)
|
152
168
|
if !arg_auth
|
153
169
|
return arg_auth, err
|
154
170
|
else
|
@@ -160,8 +176,6 @@ module GraphQL
|
|
160
176
|
end
|
161
177
|
end
|
162
178
|
|
163
|
-
private
|
164
|
-
|
165
179
|
def load_arguments(args)
|
166
180
|
prepared_args = {}
|
167
181
|
prepare_lazies = []
|
@@ -169,18 +183,14 @@ module GraphQL
|
|
169
183
|
args.each do |key, value|
|
170
184
|
arg_defn = @arguments_by_keyword[key]
|
171
185
|
if arg_defn
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
if context.schema.lazy?(prepped_value)
|
177
|
-
prepare_lazies << context.schema.after_lazy(prepped_value) do |finished_prepped_value|
|
178
|
-
prepared_args[key] = finished_prepped_value
|
179
|
-
end
|
186
|
+
prepped_value = prepared_args[key] = arg_defn.load_and_authorize_value(self, value, context)
|
187
|
+
if context.schema.lazy?(prepped_value)
|
188
|
+
prepare_lazies << context.schema.after_lazy(prepped_value) do |finished_prepped_value|
|
189
|
+
prepared_args[key] = finished_prepped_value
|
180
190
|
end
|
181
191
|
end
|
182
192
|
else
|
183
|
-
#
|
193
|
+
# these are `extras:`
|
184
194
|
prepared_args[key] = value
|
185
195
|
end
|
186
196
|
end
|
@@ -193,11 +203,23 @@ module GraphQL
|
|
193
203
|
end
|
194
204
|
end
|
195
205
|
|
196
|
-
def
|
197
|
-
|
206
|
+
def get_argument(name, context = GraphQL::Query::NullContext)
|
207
|
+
self.class.get_argument(name, context)
|
198
208
|
end
|
199
209
|
|
200
210
|
class << self
|
211
|
+
def field_arguments(context = GraphQL::Query::NullContext)
|
212
|
+
arguments(context)
|
213
|
+
end
|
214
|
+
|
215
|
+
def get_field_argument(name, context = GraphQL::Query::NullContext)
|
216
|
+
get_argument(name, context)
|
217
|
+
end
|
218
|
+
|
219
|
+
def all_field_argument_definitions
|
220
|
+
all_argument_definitions
|
221
|
+
end
|
222
|
+
|
201
223
|
# Default `:resolve` set below.
|
202
224
|
# @return [Symbol] The method to call on instances of this object to resolve the field
|
203
225
|
def resolve_method(new_method = nil)
|
@@ -217,8 +239,10 @@ module GraphQL
|
|
217
239
|
own_extras + (superclass.respond_to?(:extras) ? superclass.extras : [])
|
218
240
|
end
|
219
241
|
|
220
|
-
#
|
221
|
-
#
|
242
|
+
# If `true` (default), then the return type for this resolver will be nullable.
|
243
|
+
# If `false`, then the return type is non-null.
|
244
|
+
#
|
245
|
+
# @see #type which sets the return type of this field and accepts a `null:` option
|
222
246
|
# @param allow_null [Boolean] Whether or not the response can be null
|
223
247
|
def null(allow_null = nil)
|
224
248
|
if !allow_null.nil?
|
@@ -228,11 +252,19 @@ module GraphQL
|
|
228
252
|
@null.nil? ? (superclass.respond_to?(:null) ? superclass.null : true) : @null
|
229
253
|
end
|
230
254
|
|
255
|
+
def resolver_method(new_method_name = nil)
|
256
|
+
if new_method_name
|
257
|
+
@resolver_method = new_method_name
|
258
|
+
else
|
259
|
+
@resolver_method || :resolve_with_support
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
231
263
|
# Call this method to get the return type of the field,
|
232
264
|
# or use it as a configuration method to assign a return type
|
233
265
|
# instead of generating one.
|
234
266
|
# TODO unify with {#null}
|
235
|
-
# @param new_type [Class, nil] If a type definition class is provided, it will be used as the return type of the field
|
267
|
+
# @param new_type [Class, Array<Class>, nil] If a type definition class is provided, it will be used as the return type of the field
|
236
268
|
# @param null [true, false] Whether or not the field may return `nil`
|
237
269
|
# @return [Class] The type which this field returns.
|
238
270
|
def type(new_type = nil, null: nil)
|
@@ -243,8 +275,8 @@ module GraphQL
|
|
243
275
|
@type_expr = new_type
|
244
276
|
@null = null
|
245
277
|
else
|
246
|
-
if
|
247
|
-
GraphQL::Schema::Member::BuildType.parse_type(
|
278
|
+
if type_expr
|
279
|
+
GraphQL::Schema::Member::BuildType.parse_type(type_expr, null: self.null)
|
248
280
|
elsif superclass.respond_to?(:type)
|
249
281
|
superclass.type
|
250
282
|
else
|
@@ -262,18 +294,59 @@ module GraphQL
|
|
262
294
|
@complexity || (superclass.respond_to?(:complexity) ? superclass.complexity : 1)
|
263
295
|
end
|
264
296
|
|
265
|
-
def
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
297
|
+
def broadcastable(new_broadcastable)
|
298
|
+
@broadcastable = new_broadcastable
|
299
|
+
end
|
300
|
+
|
301
|
+
# @return [Boolean, nil]
|
302
|
+
def broadcastable?
|
303
|
+
if defined?(@broadcastable)
|
304
|
+
@broadcastable
|
305
|
+
else
|
306
|
+
(superclass.respond_to?(:broadcastable?) ? superclass.broadcastable? : nil)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
# Get or set the `max_page_size:` which will be configured for fields using this resolver
|
311
|
+
# (`nil` means "unlimited max page size".)
|
312
|
+
# @param max_page_size [Integer, nil] Set a new value
|
313
|
+
# @return [Integer, nil] The `max_page_size` assigned to fields that use this resolver
|
314
|
+
def max_page_size(new_max_page_size = :not_given)
|
315
|
+
if new_max_page_size != :not_given
|
316
|
+
@max_page_size = new_max_page_size
|
317
|
+
elsif defined?(@max_page_size)
|
318
|
+
@max_page_size
|
319
|
+
elsif superclass.respond_to?(:max_page_size)
|
320
|
+
superclass.max_page_size
|
321
|
+
else
|
322
|
+
nil
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
# @return [Boolean] `true` if this resolver or a superclass has an assigned `max_page_size`
|
327
|
+
def has_max_page_size?
|
328
|
+
(!!defined?(@max_page_size)) || (superclass.respond_to?(:has_max_page_size?) && superclass.has_max_page_size?)
|
329
|
+
end
|
330
|
+
|
331
|
+
# Get or set the `default_page_size:` which will be configured for fields using this resolver
|
332
|
+
# (`nil` means "unlimited default page size".)
|
333
|
+
# @param default_page_size [Integer, nil] Set a new value
|
334
|
+
# @return [Integer, nil] The `default_page_size` assigned to fields that use this resolver
|
335
|
+
def default_page_size(new_default_page_size = :not_given)
|
336
|
+
if new_default_page_size != :not_given
|
337
|
+
@default_page_size = new_default_page_size
|
338
|
+
elsif defined?(@default_page_size)
|
339
|
+
@default_page_size
|
340
|
+
elsif superclass.respond_to?(:default_page_size)
|
341
|
+
superclass.default_page_size
|
342
|
+
else
|
343
|
+
nil
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
# @return [Boolean] `true` if this resolver or a superclass has an assigned `default_page_size`
|
348
|
+
def has_default_page_size?
|
349
|
+
(!!defined?(@default_page_size)) || (superclass.respond_to?(:has_default_page_size?) && superclass.has_default_page_size?)
|
277
350
|
end
|
278
351
|
|
279
352
|
# A non-normalized type configuration, without `null` applied
|
@@ -285,63 +358,43 @@ module GraphQL
|
|
285
358
|
# also add some preparation hook methods which will be used for this argument
|
286
359
|
# @see {GraphQL::Schema::Argument#initialize} for the signature
|
287
360
|
def argument(*args, **kwargs, &block)
|
288
|
-
loads = kwargs[:loads]
|
289
361
|
# Use `from_resolver: true` to short-circuit the InputObject's own `loads:` implementation
|
290
362
|
# so that we can support `#load_{x}` methods below.
|
291
|
-
|
292
|
-
own_arguments_loads_as_type[arg_defn.keyword] = loads if loads
|
293
|
-
|
294
|
-
if loads && arg_defn.type.list?
|
295
|
-
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
296
|
-
def load_#{arg_defn.keyword}(values)
|
297
|
-
argument = @arguments_by_keyword[:#{arg_defn.keyword}]
|
298
|
-
lookup_as_type = @arguments_loads_as_type[:#{arg_defn.keyword}]
|
299
|
-
context.schema.after_lazy(values) do |values2|
|
300
|
-
GraphQL::Execution::Lazy.all(values2.map { |value| load_application_object(argument, lookup_as_type, value) })
|
301
|
-
end
|
302
|
-
end
|
303
|
-
RUBY
|
304
|
-
elsif loads
|
305
|
-
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
306
|
-
def load_#{arg_defn.keyword}(value)
|
307
|
-
argument = @arguments_by_keyword[:#{arg_defn.keyword}]
|
308
|
-
lookup_as_type = @arguments_loads_as_type[:#{arg_defn.keyword}]
|
309
|
-
load_application_object(argument, lookup_as_type, value)
|
310
|
-
end
|
311
|
-
RUBY
|
312
|
-
else
|
313
|
-
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
314
|
-
def load_#{arg_defn.keyword}(value)
|
315
|
-
value
|
316
|
-
end
|
317
|
-
RUBY
|
318
|
-
end
|
319
|
-
|
320
|
-
arg_defn
|
321
|
-
end
|
322
|
-
|
323
|
-
# @api private
|
324
|
-
def arguments_loads_as_type
|
325
|
-
inherited_lookups = superclass.respond_to?(:arguments_loads_as_type) ? superclass.arguments_loads_as_type : {}
|
326
|
-
inherited_lookups.merge(own_arguments_loads_as_type)
|
363
|
+
super(*args, from_resolver: true, **kwargs)
|
327
364
|
end
|
328
365
|
|
329
366
|
# Registers new extension
|
330
367
|
# @param extension [Class] Extension class
|
331
368
|
# @param options [Hash] Optional extension options
|
332
369
|
def extension(extension, **options)
|
333
|
-
|
370
|
+
@own_extensions ||= []
|
371
|
+
@own_extensions << {extension => options}
|
334
372
|
end
|
335
373
|
|
336
374
|
# @api private
|
337
375
|
def extensions
|
338
|
-
|
376
|
+
own_exts = @own_extensions
|
377
|
+
# Jump through some hoops to avoid creating arrays when we don't actually need them
|
378
|
+
if superclass.respond_to?(:extensions)
|
379
|
+
s_exts = superclass.extensions
|
380
|
+
if own_exts
|
381
|
+
if s_exts.any?
|
382
|
+
own_exts + s_exts
|
383
|
+
else
|
384
|
+
own_exts
|
385
|
+
end
|
386
|
+
else
|
387
|
+
s_exts
|
388
|
+
end
|
389
|
+
else
|
390
|
+
own_exts || EMPTY_ARRAY
|
391
|
+
end
|
339
392
|
end
|
340
393
|
|
341
394
|
private
|
342
395
|
|
343
|
-
def
|
344
|
-
@
|
396
|
+
def own_extensions
|
397
|
+
@own_extensions
|
345
398
|
end
|
346
399
|
end
|
347
400
|
end
|
@@ -2,12 +2,9 @@
|
|
2
2
|
module GraphQL
|
3
3
|
class Schema
|
4
4
|
class Scalar < GraphQL::Schema::Member
|
5
|
-
extend GraphQL::Schema::Member::
|
5
|
+
extend GraphQL::Schema::Member::ValidatesInput
|
6
6
|
|
7
7
|
class << self
|
8
|
-
extend Forwardable
|
9
|
-
def_delegators :graphql_definition, :coerce_isolated_input, :coerce_isolated_result
|
10
|
-
|
11
8
|
def coerce_input(val, ctx)
|
12
9
|
val
|
13
10
|
end
|
@@ -16,27 +13,55 @@ module GraphQL
|
|
16
13
|
val
|
17
14
|
end
|
18
15
|
|
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
|
28
|
-
end
|
29
|
-
|
30
16
|
def kind
|
31
17
|
GraphQL::TypeKinds::SCALAR
|
32
18
|
end
|
33
19
|
|
20
|
+
def specified_by_url(new_url = nil)
|
21
|
+
if new_url
|
22
|
+
@specified_by_url = new_url
|
23
|
+
elsif defined?(@specified_by_url)
|
24
|
+
@specified_by_url
|
25
|
+
elsif superclass.respond_to?(:specified_by_url)
|
26
|
+
superclass.specified_by_url
|
27
|
+
else
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
34
32
|
def default_scalar(is_default = nil)
|
35
33
|
if !is_default.nil?
|
36
34
|
@default_scalar = is_default
|
37
35
|
end
|
38
36
|
@default_scalar
|
39
37
|
end
|
38
|
+
|
39
|
+
def default_scalar?
|
40
|
+
@default_scalar ||= false
|
41
|
+
end
|
42
|
+
|
43
|
+
def validate_non_null_input(value, ctx, max_errors: nil)
|
44
|
+
coerced_result = begin
|
45
|
+
coerce_input(value, ctx)
|
46
|
+
rescue GraphQL::CoercionError => err
|
47
|
+
err
|
48
|
+
rescue StandardError => err
|
49
|
+
ctx.query.handle_or_reraise(err)
|
50
|
+
end
|
51
|
+
|
52
|
+
if coerced_result.nil?
|
53
|
+
str_value = if value == Float::INFINITY
|
54
|
+
""
|
55
|
+
else
|
56
|
+
" #{GraphQL::Language.serialize(value)}"
|
57
|
+
end
|
58
|
+
Query::InputValidationResult.from_problem("Could not coerce value#{str_value} to #{graphql_name}")
|
59
|
+
elsif coerced_result.is_a?(GraphQL::CoercionError)
|
60
|
+
Query::InputValidationResult.from_problem(coerced_result.message, message: coerced_result.message, extensions: coerced_result.extensions)
|
61
|
+
else
|
62
|
+
nil
|
63
|
+
end
|
64
|
+
end
|
40
65
|
end
|
41
66
|
end
|
42
67
|
end
|
@@ -12,19 +12,9 @@ module GraphQL
|
|
12
12
|
#
|
13
13
|
# Also, `#unsubscribe` terminates the subscription.
|
14
14
|
class Subscription < GraphQL::Schema::Resolver
|
15
|
-
class EarlyTerminationError < StandardError
|
16
|
-
end
|
17
|
-
|
18
|
-
# Raised when `unsubscribe` is called; caught by `subscriptions.rb`
|
19
|
-
class UnsubscribedError < EarlyTerminationError
|
20
|
-
end
|
21
|
-
|
22
|
-
# Raised when `no_update` is returned; caught by `subscriptions.rb`
|
23
|
-
class NoUpdateError < EarlyTerminationError
|
24
|
-
end
|
25
15
|
extend GraphQL::Schema::Resolver::HasPayloadType
|
26
16
|
extend GraphQL::Schema::Member::HasFields
|
27
|
-
|
17
|
+
NO_UPDATE = :no_update
|
28
18
|
# The generated payload type is required; If there's no payload,
|
29
19
|
# propagate null.
|
30
20
|
null false
|
@@ -35,6 +25,22 @@ module GraphQL
|
|
35
25
|
@mode = context.query.subscription_update? ? :update : :subscribe
|
36
26
|
end
|
37
27
|
|
28
|
+
def resolve_with_support(**args)
|
29
|
+
result = nil
|
30
|
+
unsubscribed = true
|
31
|
+
catch :graphql_subscription_unsubscribed do
|
32
|
+
result = super
|
33
|
+
unsubscribed = false
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
if unsubscribed
|
38
|
+
context.skip
|
39
|
+
else
|
40
|
+
result
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
38
44
|
# Implement the {Resolve} API
|
39
45
|
def resolve(**args)
|
40
46
|
# Dispatch based on `@mode`, which will raise a `NoMethodError` if we ever
|
@@ -52,11 +58,9 @@ module GraphQL
|
|
52
58
|
end
|
53
59
|
end
|
54
60
|
|
55
|
-
#
|
61
|
+
# The default implementation returns nothing on subscribe.
|
56
62
|
# Override it to return an object or
|
57
|
-
# `:no_response` to return nothing.
|
58
|
-
#
|
59
|
-
# The default is `:no_response`.
|
63
|
+
# `:no_response` to (explicitly) return nothing.
|
60
64
|
def subscribe(args = {})
|
61
65
|
:no_response
|
62
66
|
end
|
@@ -64,15 +68,16 @@ module GraphQL
|
|
64
68
|
# Wrap the user-provided `#update` hook
|
65
69
|
def resolve_update(**args)
|
66
70
|
ret_val = args.any? ? update(**args) : update
|
67
|
-
if ret_val ==
|
68
|
-
|
71
|
+
if ret_val == NO_UPDATE
|
72
|
+
context.namespace(:subscriptions)[:no_update] = true
|
73
|
+
context.skip
|
69
74
|
else
|
70
75
|
ret_val
|
71
76
|
end
|
72
77
|
end
|
73
78
|
|
74
79
|
# The default implementation returns the root object.
|
75
|
-
# Override it to return
|
80
|
+
# Override it to return {NO_UPDATE} if you want to
|
76
81
|
# skip updates sometimes. Or override it to return a different object.
|
77
82
|
def update(args = {})
|
78
83
|
object
|
@@ -90,17 +95,20 @@ module GraphQL
|
|
90
95
|
|
91
96
|
# Call this to halt execution and remove this subscription from the system
|
92
97
|
def unsubscribe
|
93
|
-
|
98
|
+
context.namespace(:subscriptions)[:unsubscribed] = true
|
99
|
+
throw :graphql_subscription_unsubscribed
|
94
100
|
end
|
95
101
|
|
102
|
+
READING_SCOPE = ::Object.new
|
96
103
|
# Call this method to provide a new subscription_scope; OR
|
97
104
|
# call it without an argument to get the subscription_scope
|
98
105
|
# @param new_scope [Symbol]
|
106
|
+
# @param optional [Boolean] If true, then don't require `scope:` to be provided to updates to this subscription.
|
99
107
|
# @return [Symbol]
|
100
|
-
|
101
|
-
def self.subscription_scope(new_scope = READING_SCOPE)
|
108
|
+
def self.subscription_scope(new_scope = READING_SCOPE, optional: false)
|
102
109
|
if new_scope != READING_SCOPE
|
103
110
|
@subscription_scope = new_scope
|
111
|
+
@subscription_scope_optional = optional
|
104
112
|
elsif defined?(@subscription_scope)
|
105
113
|
@subscription_scope
|
106
114
|
else
|
@@ -108,11 +116,32 @@ module GraphQL
|
|
108
116
|
end
|
109
117
|
end
|
110
118
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
119
|
+
def self.subscription_scope_optional?
|
120
|
+
if defined?(@subscription_scope_optional)
|
121
|
+
@subscription_scope_optional
|
122
|
+
else
|
123
|
+
find_inherited_value(:subscription_scope_optional, false)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# This is called during initial subscription to get a "name" for this subscription.
|
128
|
+
# Later, when `.trigger` is called, this will be called again to build another "name".
|
129
|
+
# Any subscribers with matching topic will begin the update flow.
|
130
|
+
#
|
131
|
+
# The default implementation creates a string using the field name, subscription scope, and argument keys and values.
|
132
|
+
# In that implementation, only `.trigger` calls with _exact matches_ result in updates to subscribers.
|
133
|
+
#
|
134
|
+
# To implement a filtered stream-type subscription flow, override this method to return a string with field name and subscription scope.
|
135
|
+
# Then, implement {#update} to compare its arguments to the current `object` and return {NO_UPDATE} when an
|
136
|
+
# update should be filtered out.
|
137
|
+
#
|
138
|
+
# @see {#update} for how to skip updates when an event comes with a matching topic.
|
139
|
+
# @param arguments [Hash<String => Object>] The arguments for this topic, in GraphQL-style (camelized strings)
|
140
|
+
# @param field [GraphQL::Schema::Field]
|
141
|
+
# @param scope [Object, nil] A value corresponding to `.trigger(... scope:)` (for updates) or the `subscription_scope` found in `context` (for initial subscriptions).
|
142
|
+
# @return [String] An identifier corresponding to a stream of updates
|
143
|
+
def self.topic_for(arguments:, field:, scope:)
|
144
|
+
Subscriptions::Serialize.dump_recursive([scope, field.graphql_name, arguments])
|
116
145
|
end
|
117
146
|
end
|
118
147
|
end
|
@@ -7,7 +7,7 @@ module GraphQL
|
|
7
7
|
# to the `errors` key. Any already-resolved fields will be in the `data` key, so
|
8
8
|
# you'll get a partial response.
|
9
9
|
#
|
10
|
-
# You can subclass `GraphQL::Schema::Timeout` and override
|
10
|
+
# You can subclass `GraphQL::Schema::Timeout` and override `max_seconds` and/or `handle_timeout`
|
11
11
|
# to provide custom logic when a timeout error occurs.
|
12
12
|
#
|
13
13
|
# Note that this will stop a query _in between_ field resolutions, but
|
@@ -33,8 +33,6 @@ module GraphQL
|
|
33
33
|
# end
|
34
34
|
#
|
35
35
|
class Timeout
|
36
|
-
attr_reader :max_seconds
|
37
|
-
|
38
36
|
def self.use(schema, **options)
|
39
37
|
tracer = new(**options)
|
40
38
|
schema.tracer(tracer)
|
@@ -48,32 +46,39 @@ module GraphQL
|
|
48
46
|
def trace(key, data)
|
49
47
|
case key
|
50
48
|
when 'execute_multiplex'
|
51
|
-
timeout_state = {
|
52
|
-
timeout_at: Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond) + max_seconds * 1000,
|
53
|
-
timed_out: false
|
54
|
-
}
|
55
|
-
|
56
49
|
data.fetch(:multiplex).queries.each do |query|
|
50
|
+
timeout_duration_s = max_seconds(query)
|
51
|
+
timeout_state = if timeout_duration_s == false
|
52
|
+
# if the method returns `false`, don't apply a timeout
|
53
|
+
false
|
54
|
+
else
|
55
|
+
now = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
|
56
|
+
timeout_at = now + (max_seconds(query) * 1000)
|
57
|
+
{
|
58
|
+
timeout_at: timeout_at,
|
59
|
+
timed_out: false
|
60
|
+
}
|
61
|
+
end
|
57
62
|
query.context.namespace(self.class)[:state] = timeout_state
|
58
63
|
end
|
59
64
|
|
60
65
|
yield
|
61
66
|
when 'execute_field', 'execute_field_lazy'
|
62
|
-
|
63
|
-
timeout_state =
|
64
|
-
|
67
|
+
query_context = data[:context] || data[:query].context
|
68
|
+
timeout_state = query_context.namespace(self.class).fetch(:state)
|
69
|
+
# If the `:state` is `false`, then `max_seconds(query)` opted out of timeout for this query.
|
70
|
+
if timeout_state != false && Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond) > timeout_state.fetch(:timeout_at)
|
65
71
|
error = if data[:context]
|
66
|
-
|
67
|
-
GraphQL::Schema::Timeout::TimeoutError.new(context.parent_type, context.field)
|
72
|
+
GraphQL::Schema::Timeout::TimeoutError.new(query_context.parent_type, query_context.field)
|
68
73
|
else
|
69
74
|
field = data.fetch(:field)
|
70
75
|
GraphQL::Schema::Timeout::TimeoutError.new(field.owner, field)
|
71
76
|
end
|
72
77
|
|
73
78
|
# Only invoke the timeout callback for the first timeout
|
74
|
-
|
79
|
+
if !timeout_state[:timed_out]
|
75
80
|
timeout_state[:timed_out] = true
|
76
|
-
handle_timeout(error, query)
|
81
|
+
handle_timeout(error, query_context.query)
|
77
82
|
end
|
78
83
|
|
79
84
|
error
|
@@ -85,6 +90,15 @@ module GraphQL
|
|
85
90
|
end
|
86
91
|
end
|
87
92
|
|
93
|
+
# Called at the start of each query.
|
94
|
+
# The default implementation returns the `max_seconds:` value from installing this plugin.
|
95
|
+
#
|
96
|
+
# @param query [GraphQL::Query] The query that's about to run
|
97
|
+
# @return [Integer, false] The number of seconds after which to interrupt query execution and call {#handle_error}, or `false` to bypass the timeout.
|
98
|
+
def max_seconds(query)
|
99
|
+
@max_seconds
|
100
|
+
end
|
101
|
+
|
88
102
|
# Invoked when a query times out.
|
89
103
|
# @param error [GraphQL::Schema::Timeout::TimeoutError]
|
90
104
|
# @param query [GraphQL::Error]
|