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
data/lib/graphql/schema/field.rb
CHANGED
@@ -5,14 +5,13 @@ require "graphql/schema/field/scope_extension"
|
|
5
5
|
module GraphQL
|
6
6
|
class Schema
|
7
7
|
class Field
|
8
|
-
include GraphQL::Schema::Member::CachedGraphQLDefinition
|
9
|
-
include GraphQL::Schema::Member::AcceptsDefinition
|
10
8
|
include GraphQL::Schema::Member::HasArguments
|
9
|
+
include GraphQL::Schema::Member::HasArguments::FieldConfigured
|
11
10
|
include GraphQL::Schema::Member::HasAstNode
|
12
11
|
include GraphQL::Schema::Member::HasPath
|
13
12
|
include GraphQL::Schema::Member::HasValidators
|
14
13
|
extend GraphQL::Schema::FindInheritedValue
|
15
|
-
include GraphQL::
|
14
|
+
include GraphQL::EmptyObjects
|
16
15
|
include GraphQL::Schema::Member::HasDirectives
|
17
16
|
include GraphQL::Schema::Member::HasDeprecationReason
|
18
17
|
|
@@ -30,8 +29,43 @@ module GraphQL
|
|
30
29
|
# @return [String] Method or hash key on the underlying object to look up
|
31
30
|
attr_reader :method_str
|
32
31
|
|
32
|
+
attr_reader :hash_key
|
33
|
+
attr_reader :dig_keys
|
34
|
+
|
33
35
|
# @return [Symbol] The method on the type to look up
|
34
|
-
|
36
|
+
def resolver_method
|
37
|
+
if @resolver_class
|
38
|
+
@resolver_class.resolver_method
|
39
|
+
else
|
40
|
+
@resolver_method
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# @return [String, nil]
|
45
|
+
def deprecation_reason
|
46
|
+
super || @resolver_class&.deprecation_reason
|
47
|
+
end
|
48
|
+
|
49
|
+
def directives
|
50
|
+
if @resolver_class && !(r_dirs = @resolver_class.directives).empty?
|
51
|
+
if !(own_dirs = super).empty?
|
52
|
+
new_dirs = own_dirs.dup
|
53
|
+
r_dirs.each do |r_dir|
|
54
|
+
if r_dir.class.repeatable? ||
|
55
|
+
( (r_dir_name = r_dir.graphql_name) &&
|
56
|
+
(!new_dirs.any? { |d| d.graphql_name == r_dir_name })
|
57
|
+
)
|
58
|
+
new_dirs << r_dir
|
59
|
+
end
|
60
|
+
end
|
61
|
+
new_dirs
|
62
|
+
else
|
63
|
+
r_dirs
|
64
|
+
end
|
65
|
+
else
|
66
|
+
super
|
67
|
+
end
|
68
|
+
end
|
35
69
|
|
36
70
|
# @return [Class] The thing this field was defined on (type, mutation, resolver)
|
37
71
|
attr_accessor :owner
|
@@ -61,7 +95,7 @@ module GraphQL
|
|
61
95
|
end
|
62
96
|
|
63
97
|
def inspect
|
64
|
-
"#<#{self.class} #{path}#{all_argument_definitions.
|
98
|
+
"#<#{self.class} #{path}#{!all_argument_definitions.empty? ? "(...)" : ""}: #{type.to_type_signature}>"
|
65
99
|
end
|
66
100
|
|
67
101
|
alias :mutation :resolver
|
@@ -70,7 +104,10 @@ module GraphQL
|
|
70
104
|
attr_reader :trace
|
71
105
|
|
72
106
|
# @return [String, nil]
|
73
|
-
|
107
|
+
def subscription_scope
|
108
|
+
@subscription_scope || (@resolver_class.respond_to?(:subscription_scope) ? @resolver_class.subscription_scope : nil)
|
109
|
+
end
|
110
|
+
attr_writer :subscription_scope
|
74
111
|
|
75
112
|
# Create a field instance from a list of arguments, keyword arguments, and a block.
|
76
113
|
#
|
@@ -81,34 +118,23 @@ module GraphQL
|
|
81
118
|
# @param resolver [Class] A {GraphQL::Schema::Resolver} class to use for field configuration
|
82
119
|
# @param mutation [Class] A {GraphQL::Schema::Mutation} class to use for field configuration
|
83
120
|
# @param subscription [Class] A {GraphQL::Schema::Subscription} class to use for field configuration
|
84
|
-
# @return [GraphQL::Schema:Field] an instance of `self
|
121
|
+
# @return [GraphQL::Schema:Field] an instance of `self`
|
85
122
|
# @see {.initialize} for other options
|
86
|
-
def self.from_options(name = nil, type = nil, desc = nil, resolver: nil, mutation: nil, subscription: nil,**kwargs, &block)
|
87
|
-
if
|
88
|
-
if kwargs[:field].is_a?(GraphQL::Field) && kwargs[:field] == GraphQL::Types::Relay::NodeField.graphql_definition
|
89
|
-
GraphQL::Deprecation.warn("Legacy-style `GraphQL::Relay::Node.field` is being added to a class-based type. See `GraphQL::Types::Relay::NodeField` for a replacement.")
|
90
|
-
return GraphQL::Types::Relay::NodeField
|
91
|
-
elsif kwargs[:field].is_a?(GraphQL::Field) && kwargs[:field] == GraphQL::Types::Relay::NodesField.graphql_definition
|
92
|
-
GraphQL::Deprecation.warn("Legacy-style `GraphQL::Relay::Node.plural_field` is being added to a class-based type. See `GraphQL::Types::Relay::NodesField` for a replacement.")
|
93
|
-
return GraphQL::Types::Relay::NodesField
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
if (parent_config = resolver || mutation || subscription)
|
98
|
-
# Get the parent config, merge in local overrides
|
99
|
-
kwargs = parent_config.field_options.merge(kwargs)
|
123
|
+
def self.from_options(name = nil, type = nil, desc = nil, comment: nil, resolver: nil, mutation: nil, subscription: nil,**kwargs, &block)
|
124
|
+
if (resolver_class = resolver || mutation || subscription)
|
100
125
|
# Add a reference to that parent class
|
101
|
-
kwargs[:resolver_class] =
|
126
|
+
kwargs[:resolver_class] = resolver_class
|
102
127
|
end
|
103
128
|
|
104
129
|
if name
|
105
130
|
kwargs[:name] = name
|
106
131
|
end
|
107
132
|
|
133
|
+
if comment
|
134
|
+
kwargs[:comment] = comment
|
135
|
+
end
|
136
|
+
|
108
137
|
if !type.nil?
|
109
|
-
if type.is_a?(GraphQL::Field)
|
110
|
-
raise ArgumentError, "A GraphQL::Field was passed as the second argument, use the `field:` keyword for this instead."
|
111
|
-
end
|
112
138
|
if desc
|
113
139
|
if kwargs[:description]
|
114
140
|
raise ArgumentError, "Provide description as a positional argument or `description:` keyword, but not both (#{desc.inspect}, #{kwargs[:description].inspect})"
|
@@ -116,8 +142,8 @@ module GraphQL
|
|
116
142
|
|
117
143
|
kwargs[:description] = desc
|
118
144
|
kwargs[:type] = type
|
119
|
-
elsif (
|
120
|
-
# The return type should be copied from
|
145
|
+
elsif (resolver || mutation) && type.is_a?(String)
|
146
|
+
# The return type should be copied from the resolver, and the second positional argument is the description
|
121
147
|
kwargs[:description] = type
|
122
148
|
else
|
123
149
|
kwargs[:type] = type
|
@@ -134,15 +160,20 @@ module GraphQL
|
|
134
160
|
def connection?
|
135
161
|
if @connection.nil?
|
136
162
|
# Provide default based on type name
|
137
|
-
return_type_name = if
|
138
|
-
Member::BuildType.to_type_name(contains_type.type)
|
139
|
-
elsif @return_type_expr
|
163
|
+
return_type_name = if @return_type_expr
|
140
164
|
Member::BuildType.to_type_name(@return_type_expr)
|
141
|
-
|
165
|
+
elsif @resolver_class && @resolver_class.type
|
166
|
+
Member::BuildType.to_type_name(@resolver_class.type)
|
167
|
+
elsif type
|
142
168
|
# As a last ditch, try to force loading the return type:
|
143
169
|
type.unwrap.name
|
144
170
|
end
|
145
|
-
|
171
|
+
if return_type_name
|
172
|
+
@connection = return_type_name.end_with?("Connection") && return_type_name != "Connection"
|
173
|
+
else
|
174
|
+
# TODO set this when type is set by method
|
175
|
+
false # not loaded yet?
|
176
|
+
end
|
146
177
|
else
|
147
178
|
@connection
|
148
179
|
end
|
@@ -153,8 +184,18 @@ module GraphQL
|
|
153
184
|
if !@scope.nil?
|
154
185
|
# The default was overridden
|
155
186
|
@scope
|
187
|
+
elsif @return_type_expr
|
188
|
+
# Detect a list return type, but don't call `type` since that may eager-load an otherwise lazy-loaded type
|
189
|
+
@return_type_expr.is_a?(Array) ||
|
190
|
+
(@return_type_expr.is_a?(String) && @return_type_expr.include?("[")) ||
|
191
|
+
connection?
|
192
|
+
elsif @resolver_class
|
193
|
+
resolver_type = @resolver_class.type_expr
|
194
|
+
resolver_type.is_a?(Array) ||
|
195
|
+
(resolver_type.is_a?(String) && resolver_type.include?("[")) ||
|
196
|
+
connection?
|
156
197
|
else
|
157
|
-
|
198
|
+
false
|
158
199
|
end
|
159
200
|
end
|
160
201
|
|
@@ -187,8 +228,9 @@ module GraphQL
|
|
187
228
|
# @param name [Symbol] The underscore-cased version of this field name (will be camelized for the GraphQL API)
|
188
229
|
# @param type [Class, GraphQL::BaseType, Array] The return type of this field
|
189
230
|
# @param owner [Class] The type that this field belongs to
|
190
|
-
# @param null [Boolean] `true` if this field may return `null`, `false` if it is never `null`
|
231
|
+
# @param null [Boolean] (defaults to `true`) `true` if this field may return `null`, `false` if it is never `null`
|
191
232
|
# @param description [String] Field description
|
233
|
+
# @param comment [String] Field comment
|
192
234
|
# @param deprecation_reason [String] If present, the field is marked "deprecated" with this message
|
193
235
|
# @param method [Symbol] The method to call on the underlying object to resolve this field (defaults to `name`)
|
194
236
|
# @param hash_key [String, Symbol] The hash key to lookup on the underlying object (if its a Hash) to resolve this field (defaults to `name` or `name.to_s`)
|
@@ -197,10 +239,8 @@ module GraphQL
|
|
197
239
|
# @param connection [Boolean] `true` if this field should get automagic connection behavior; default is to infer by `*Connection` in the return type name
|
198
240
|
# @param connection_extension [Class] The extension to add, to implement connections. If `nil`, no extension is added.
|
199
241
|
# @param max_page_size [Integer, nil] For connections, the maximum number of items to return from this field, or `nil` to allow unlimited results.
|
242
|
+
# @param default_page_size [Integer, nil] For connections, the default number of items to return from this field, or `nil` to return unlimited results.
|
200
243
|
# @param introspection [Boolean] If true, this field will be marked as `#introspection?` and the name may begin with `__`
|
201
|
-
# @param resolve [<#call(obj, args, ctx)>] **deprecated** for compatibility with <1.8.0
|
202
|
-
# @param field [GraphQL::Field, GraphQL::Schema::Field] **deprecated** for compatibility with <1.8.0
|
203
|
-
# @param function [GraphQL::Function] **deprecated** for compatibility with <1.8.0
|
204
244
|
# @param resolver_class [Class] (Private) A {Schema::Resolver} which this field was derived from. Use `resolver:` to create a field with a resolver.
|
205
245
|
# @param arguments [{String=>GraphQL::Schema::Argument, Hash}] Arguments for this field (may be added in the block, also)
|
206
246
|
# @param camelize [Boolean] If true, the field name will be camelized when building the schema
|
@@ -214,19 +254,16 @@ module GraphQL
|
|
214
254
|
# @param ast_node [Language::Nodes::FieldDefinition, nil] If this schema was parsed from definition, this AST node defined the field
|
215
255
|
# @param method_conflict_warning [Boolean] If false, skip the warning if this field's method conflicts with a built-in method
|
216
256
|
# @param validates [Array<Hash>] Configurations for validating this field
|
217
|
-
# @param
|
218
|
-
def initialize(type: nil, name: nil, owner: nil, null:
|
257
|
+
# @param fallback_value [Object] A fallback value if the method is not defined
|
258
|
+
def initialize(type: nil, name: nil, owner: nil, null: nil, description: NOT_CONFIGURED, comment: NOT_CONFIGURED, deprecation_reason: nil, method: nil, hash_key: nil, dig: nil, resolver_method: nil, connection: nil, max_page_size: NOT_CONFIGURED, default_page_size: NOT_CONFIGURED, scope: nil, introspection: false, camelize: true, trace: nil, complexity: nil, ast_node: nil, extras: EMPTY_ARRAY, extensions: EMPTY_ARRAY, connection_extension: self.class.connection_extension, resolver_class: nil, subscription_scope: nil, relay_node_field: false, relay_nodes_field: false, method_conflict_warning: true, broadcastable: NOT_CONFIGURED, arguments: EMPTY_HASH, directives: EMPTY_HASH, validates: EMPTY_ARRAY, fallback_value: NOT_CONFIGURED, dynamic_introspection: false, &definition_block)
|
219
259
|
if name.nil?
|
220
260
|
raise ArgumentError, "missing first `name` argument or keyword `name:`"
|
221
261
|
end
|
222
|
-
if !(
|
223
|
-
if type.nil?
|
224
|
-
raise ArgumentError, "missing second `type` argument or
|
262
|
+
if !(resolver_class)
|
263
|
+
if type.nil? && !block_given?
|
264
|
+
raise ArgumentError, "missing second `type` argument, keyword `type:`, or a block containing `type(...)`"
|
225
265
|
end
|
226
266
|
end
|
227
|
-
if (field || function || resolve) && extras.any?
|
228
|
-
raise ArgumentError, "keyword `extras:` may only be used with method-based resolve and class-based field such as mutation class, please remove `field:`, `function:` or `resolve:`"
|
229
|
-
end
|
230
267
|
@original_name = name
|
231
268
|
name_s = -name.to_s
|
232
269
|
|
@@ -234,13 +271,9 @@ module GraphQL
|
|
234
271
|
@name = -(camelize ? Member::BuildType.camelize(name_s) : name_s)
|
235
272
|
NameValidator.validate!(@name)
|
236
273
|
@description = description
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
@field = field
|
241
|
-
end
|
242
|
-
@function = function
|
243
|
-
@resolve = resolve
|
274
|
+
@comment = comment
|
275
|
+
@type = @owner_type = @own_validators = @own_directives = @own_arguments = @arguments_statically_coercible = nil # these will be prepared later if necessary
|
276
|
+
|
244
277
|
self.deprecation_reason = deprecation_reason
|
245
278
|
|
246
279
|
if method && hash_key && dig
|
@@ -257,24 +290,32 @@ module GraphQL
|
|
257
290
|
end
|
258
291
|
end
|
259
292
|
|
260
|
-
# TODO: I think non-string/symbol hash keys are wrongly normalized (eg `1` will not work)
|
261
293
|
method_name = method || hash_key || name_s
|
262
294
|
@dig_keys = dig
|
263
295
|
if hash_key
|
264
296
|
@hash_key = hash_key
|
297
|
+
@hash_key_str = hash_key.to_s
|
298
|
+
else
|
299
|
+
@hash_key = NOT_CONFIGURED
|
300
|
+
@hash_key_str = NOT_CONFIGURED
|
265
301
|
end
|
266
302
|
|
267
|
-
resolver_method ||= name_s.to_sym
|
268
|
-
|
269
303
|
@method_str = -method_name.to_s
|
270
304
|
@method_sym = method_name.to_sym
|
271
|
-
@resolver_method = resolver_method
|
305
|
+
@resolver_method = (resolver_method || name_s).to_sym
|
272
306
|
@complexity = complexity
|
307
|
+
@dynamic_introspection = dynamic_introspection
|
273
308
|
@return_type_expr = type
|
274
|
-
@return_type_null = null
|
309
|
+
@return_type_null = if !null.nil?
|
310
|
+
null
|
311
|
+
elsif resolver_class
|
312
|
+
nil
|
313
|
+
else
|
314
|
+
true
|
315
|
+
end
|
275
316
|
@connection = connection
|
276
|
-
@
|
277
|
-
@
|
317
|
+
@max_page_size = max_page_size
|
318
|
+
@default_page_size = default_page_size
|
278
319
|
@introspection = introspection
|
279
320
|
@extras = extras
|
280
321
|
@broadcastable = broadcastable
|
@@ -285,7 +326,8 @@ module GraphQL
|
|
285
326
|
@relay_nodes_field = relay_nodes_field
|
286
327
|
@ast_node = ast_node
|
287
328
|
@method_conflict_warning = method_conflict_warning
|
288
|
-
@
|
329
|
+
@fallback_value = fallback_value
|
330
|
+
@definition_block = definition_block
|
289
331
|
|
290
332
|
arguments.each do |name, arg|
|
291
333
|
case arg
|
@@ -305,48 +347,64 @@ module GraphQL
|
|
305
347
|
|
306
348
|
@extensions = EMPTY_ARRAY
|
307
349
|
@call_after_define = false
|
308
|
-
|
309
|
-
# but should it run after the definition block?
|
310
|
-
if scoped?
|
311
|
-
self.extension(ScopeExtension)
|
312
|
-
end
|
313
|
-
|
314
|
-
# The problem with putting this after the definition_block
|
315
|
-
# is that it would override arguments
|
316
|
-
if connection? && connection_extension
|
317
|
-
self.extension(connection_extension)
|
318
|
-
end
|
319
|
-
|
350
|
+
set_pagination_extensions(connection_extension: connection_extension)
|
320
351
|
# Do this last so we have as much context as possible when initializing them:
|
321
|
-
if extensions.
|
352
|
+
if !extensions.empty?
|
322
353
|
self.extensions(extensions)
|
323
354
|
end
|
324
355
|
|
325
|
-
if
|
356
|
+
if resolver_class && !resolver_class.extensions.empty?
|
357
|
+
self.extensions(resolver_class.extensions)
|
358
|
+
end
|
359
|
+
|
360
|
+
if !directives.empty?
|
326
361
|
directives.each do |(dir_class, options)|
|
327
362
|
self.directive(dir_class, **options)
|
328
363
|
end
|
329
364
|
end
|
330
365
|
|
331
|
-
|
366
|
+
if !validates.empty?
|
367
|
+
self.validates(validates)
|
368
|
+
end
|
332
369
|
|
333
|
-
if definition_block
|
334
|
-
|
335
|
-
|
370
|
+
if @definition_block.nil?
|
371
|
+
self.extensions.each(&:after_define_apply)
|
372
|
+
@call_after_define = true
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
# Calls the definition block, if one was given.
|
377
|
+
# This is deferred so that references to the return type
|
378
|
+
# can be lazily evaluated, reducing Rails boot time.
|
379
|
+
# @return [self]
|
380
|
+
# @api private
|
381
|
+
def ensure_loaded
|
382
|
+
if @definition_block
|
383
|
+
if @definition_block.arity == 1
|
384
|
+
@definition_block.call(self)
|
336
385
|
else
|
337
|
-
|
386
|
+
instance_exec(self, &@definition_block)
|
338
387
|
end
|
388
|
+
self.extensions.each(&:after_define_apply)
|
389
|
+
@call_after_define = true
|
390
|
+
@definition_block = nil
|
339
391
|
end
|
340
|
-
|
341
|
-
self.extensions.each(&:after_define_apply)
|
342
|
-
@call_after_define = true
|
392
|
+
self
|
343
393
|
end
|
344
394
|
|
395
|
+
attr_accessor :dynamic_introspection
|
396
|
+
|
345
397
|
# If true, subscription updates with this field can be shared between viewers
|
346
398
|
# @return [Boolean, nil]
|
347
399
|
# @see GraphQL::Subscriptions::BroadcastAnalyzer
|
348
400
|
def broadcastable?
|
349
|
-
@broadcastable
|
401
|
+
if !NOT_CONFIGURED.equal?(@broadcastable)
|
402
|
+
@broadcastable
|
403
|
+
elsif @resolver_class
|
404
|
+
@resolver_class.broadcastable?
|
405
|
+
else
|
406
|
+
nil
|
407
|
+
end
|
350
408
|
end
|
351
409
|
|
352
410
|
# @param text [String]
|
@@ -354,8 +412,26 @@ module GraphQL
|
|
354
412
|
def description(text = nil)
|
355
413
|
if text
|
356
414
|
@description = text
|
357
|
-
|
415
|
+
elsif !NOT_CONFIGURED.equal?(@description)
|
358
416
|
@description
|
417
|
+
elsif @resolver_class
|
418
|
+
@resolver_class.description
|
419
|
+
else
|
420
|
+
nil
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
# @param text [String]
|
425
|
+
# @return [String, nil]
|
426
|
+
def comment(text = nil)
|
427
|
+
if text
|
428
|
+
@comment = text
|
429
|
+
elsif !NOT_CONFIGURED.equal?(@comment)
|
430
|
+
@comment
|
431
|
+
elsif @resolver_class
|
432
|
+
@resolver_class.comment
|
433
|
+
else
|
434
|
+
nil
|
359
435
|
end
|
360
436
|
end
|
361
437
|
|
@@ -379,7 +455,7 @@ module GraphQL
|
|
379
455
|
new_extensions.each do |extension_config|
|
380
456
|
if extension_config.is_a?(Hash)
|
381
457
|
extension_class, options = *extension_config.to_a[0]
|
382
|
-
self.extension(extension_class, options)
|
458
|
+
self.extension(extension_class, **options)
|
383
459
|
else
|
384
460
|
self.extension(extension_config)
|
385
461
|
end
|
@@ -399,7 +475,7 @@ module GraphQL
|
|
399
475
|
# @param extension_class [Class] subclass of {Schema::FieldExtension}
|
400
476
|
# @param options [Hash] if provided, given as `options:` when initializing `extension`.
|
401
477
|
# @return [void]
|
402
|
-
def extension(extension_class, options
|
478
|
+
def extension(extension_class, **options)
|
403
479
|
extension_inst = extension_class.new(field: self, options: options)
|
404
480
|
if @extensions.frozen?
|
405
481
|
@extensions = @extensions.dup
|
@@ -419,7 +495,12 @@ module GraphQL
|
|
419
495
|
def extras(new_extras = nil)
|
420
496
|
if new_extras.nil?
|
421
497
|
# Read the value
|
422
|
-
@extras
|
498
|
+
field_extras = @extras
|
499
|
+
if @resolver_class && !@resolver_class.extras.empty?
|
500
|
+
field_extras + @resolver_class.extras
|
501
|
+
else
|
502
|
+
field_extras
|
503
|
+
end
|
423
504
|
else
|
424
505
|
if @extras.frozen?
|
425
506
|
@extras = @extras.dup
|
@@ -444,53 +525,38 @@ module GraphQL
|
|
444
525
|
if arguments[:last] && (max_possible_page_size.nil? || arguments[:last] > max_possible_page_size)
|
445
526
|
max_possible_page_size = arguments[:last]
|
446
527
|
end
|
528
|
+
elsif arguments.is_a?(GraphQL::ExecutionError) || arguments.is_a?(GraphQL::UnauthorizedError)
|
529
|
+
raise arguments
|
447
530
|
end
|
448
531
|
|
449
532
|
if max_possible_page_size.nil?
|
450
|
-
max_possible_page_size = max_page_size || query.schema.default_max_page_size
|
533
|
+
max_possible_page_size = default_page_size || query.schema.default_page_size || max_page_size || query.schema.default_max_page_size
|
451
534
|
end
|
452
535
|
|
453
536
|
if max_possible_page_size.nil?
|
454
|
-
raise GraphQL::Error, "Can't calculate complexity for #{path}, no `first:`, `last:`, `max_page_size` or `default_max_page_size`"
|
537
|
+
raise GraphQL::Error, "Can't calculate complexity for #{path}, no `first:`, `last:`, `default_page_size`, `max_page_size` or `default_max_page_size`"
|
455
538
|
else
|
456
539
|
metadata_complexity = 0
|
457
540
|
lookahead = GraphQL::Execution::Lookahead.new(query: query, field: self, ast_nodes: nodes, owner_type: owner)
|
458
541
|
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
542
|
+
lookahead.selections.each do |next_lookahead|
|
543
|
+
# this includes `pageInfo`, `nodes` and `edges` and any custom fields
|
544
|
+
# TODO this doesn't support procs yet -- unlikely to need it.
|
545
|
+
metadata_complexity += next_lookahead.field.complexity
|
546
|
+
if next_lookahead.name != :nodes && next_lookahead.name != :edges
|
547
|
+
# subfields, eg, for pageInfo -- assumes no subselections
|
548
|
+
metadata_complexity += next_lookahead.selections.size
|
549
|
+
end
|
466
550
|
end
|
467
551
|
|
468
|
-
nodes_edges_complexity = 0
|
469
|
-
nodes_edges_complexity += 1 if lookahead.selects?(:edges)
|
470
|
-
nodes_edges_complexity += 1 if lookahead.selects?(:nodes)
|
471
|
-
|
472
552
|
# Possible bug: selections on `edges` and `nodes` are _both_ multiplied here. Should they be?
|
473
|
-
items_complexity = child_complexity - metadata_complexity
|
474
|
-
|
475
|
-
|
553
|
+
items_complexity = child_complexity - metadata_complexity
|
554
|
+
subfields_complexity = (max_possible_page_size * items_complexity) + metadata_complexity
|
555
|
+
# Apply this field's own complexity
|
556
|
+
apply_own_complexity_to(subfields_complexity, query, nodes)
|
476
557
|
end
|
477
558
|
else
|
478
|
-
|
479
|
-
case defined_complexity
|
480
|
-
when Proc
|
481
|
-
arguments = query.arguments_for(nodes.first, self)
|
482
|
-
if arguments.is_a?(GraphQL::ExecutionError)
|
483
|
-
return child_complexity
|
484
|
-
elsif arguments.respond_to?(:keyword_arguments)
|
485
|
-
arguments = arguments.keyword_arguments
|
486
|
-
end
|
487
|
-
|
488
|
-
defined_complexity.call(query.context, arguments, child_complexity)
|
489
|
-
when Numeric
|
490
|
-
defined_complexity + child_complexity
|
491
|
-
else
|
492
|
-
raise("Invalid complexity: #{defined_complexity.inspect} on #{path} (#{inspect})")
|
493
|
-
end
|
559
|
+
apply_own_complexity_to(child_complexity, query, nodes)
|
494
560
|
end
|
495
561
|
end
|
496
562
|
|
@@ -508,7 +574,11 @@ module GraphQL
|
|
508
574
|
when Numeric
|
509
575
|
@complexity = new_complexity
|
510
576
|
when nil
|
511
|
-
@
|
577
|
+
if @resolver_class
|
578
|
+
@complexity || @resolver_class.complexity || 1
|
579
|
+
else
|
580
|
+
@complexity || 1
|
581
|
+
end
|
512
582
|
else
|
513
583
|
raise("Invalid complexity: #{new_complexity.inspect} on #{@name}")
|
514
584
|
end
|
@@ -516,105 +586,70 @@ module GraphQL
|
|
516
586
|
|
517
587
|
# @return [Boolean] True if this field's {#max_page_size} should override the schema default.
|
518
588
|
def has_max_page_size?
|
519
|
-
@has_max_page_size
|
589
|
+
!NOT_CONFIGURED.equal?(@max_page_size) || (@resolver_class && @resolver_class.has_max_page_size?)
|
520
590
|
end
|
521
591
|
|
522
592
|
# @return [Integer, nil] Applied to connections if {#has_max_page_size?}
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
def to_graphql
|
529
|
-
field_defn = if @field
|
530
|
-
@field.dup
|
531
|
-
elsif @function
|
532
|
-
GraphQL::Function.build_field(@function)
|
593
|
+
def max_page_size
|
594
|
+
if !NOT_CONFIGURED.equal?(@max_page_size)
|
595
|
+
@max_page_size
|
596
|
+
elsif @resolver_class && @resolver_class.has_max_page_size?
|
597
|
+
@resolver_class.max_page_size
|
533
598
|
else
|
534
|
-
|
535
|
-
end
|
536
|
-
|
537
|
-
field_defn.name = @name
|
538
|
-
if @return_type_expr
|
539
|
-
field_defn.type = -> { type }
|
599
|
+
nil
|
540
600
|
end
|
601
|
+
end
|
541
602
|
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
if self.deprecation_reason
|
547
|
-
field_defn.deprecation_reason = self.deprecation_reason
|
548
|
-
end
|
549
|
-
|
550
|
-
if @resolver_class
|
551
|
-
if @resolver_class < GraphQL::Schema::Mutation
|
552
|
-
field_defn.mutation = @resolver_class
|
553
|
-
end
|
554
|
-
field_defn.metadata[:resolver] = @resolver_class
|
555
|
-
end
|
556
|
-
|
557
|
-
if !@trace.nil?
|
558
|
-
field_defn.trace = @trace
|
559
|
-
end
|
560
|
-
|
561
|
-
if @relay_node_field
|
562
|
-
field_defn.relay_node_field = @relay_node_field
|
563
|
-
end
|
564
|
-
|
565
|
-
if @relay_nodes_field
|
566
|
-
field_defn.relay_nodes_field = @relay_nodes_field
|
567
|
-
end
|
568
|
-
|
569
|
-
if @legacy_edge_class
|
570
|
-
field_defn.edge_class = @legacy_edge_class
|
571
|
-
end
|
572
|
-
|
573
|
-
field_defn.resolve = self.method(:resolve_field)
|
574
|
-
field_defn.connection = connection?
|
575
|
-
field_defn.connection_max_page_size = max_page_size
|
576
|
-
field_defn.introspection = @introspection
|
577
|
-
field_defn.complexity = @complexity
|
578
|
-
field_defn.subscription_scope = @subscription_scope
|
579
|
-
field_defn.ast_node = ast_node
|
580
|
-
|
581
|
-
all_argument_definitions.each do |defn|
|
582
|
-
arg_graphql = defn.deprecated_to_graphql
|
583
|
-
field_defn.arguments[arg_graphql.name] = arg_graphql # rubocop:disable Development/ContextIsPassedCop -- legacy-related
|
584
|
-
end
|
603
|
+
# @return [Boolean] True if this field's {#default_page_size} should override the schema default.
|
604
|
+
def has_default_page_size?
|
605
|
+
!NOT_CONFIGURED.equal?(@default_page_size) || (@resolver_class && @resolver_class.has_default_page_size?)
|
606
|
+
end
|
585
607
|
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
608
|
+
# @return [Integer, nil] Applied to connections if {#has_default_page_size?}
|
609
|
+
def default_page_size
|
610
|
+
if !NOT_CONFIGURED.equal?(@default_page_size)
|
611
|
+
@default_page_size
|
612
|
+
elsif @resolver_class && @resolver_class.has_default_page_size?
|
613
|
+
@resolver_class.default_page_size
|
614
|
+
else
|
615
|
+
nil
|
593
616
|
end
|
617
|
+
end
|
594
618
|
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
619
|
+
def freeze
|
620
|
+
type
|
621
|
+
owner_type
|
622
|
+
arguments_statically_coercible?
|
623
|
+
connection?
|
624
|
+
super
|
599
625
|
end
|
600
626
|
|
601
627
|
class MissingReturnTypeError < GraphQL::Error; end
|
602
628
|
attr_writer :type
|
603
629
|
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
message = "Can't determine the return type for #{self.path}"
|
630
|
+
# Get or set the return type of this field.
|
631
|
+
#
|
632
|
+
# It may return nil if no type was configured or if the given definition block wasn't called yet.
|
633
|
+
# @param new_type [Module, GraphQL::Schema::NonNull, GraphQL::Schema::List] A GraphQL return type
|
634
|
+
# @return [Module, GraphQL::Schema::NonNull, GraphQL::Schema::List, nil] the configured type for this field
|
635
|
+
def type(new_type = NOT_CONFIGURED)
|
636
|
+
if NOT_CONFIGURED.equal?(new_type)
|
612
637
|
if @resolver_class
|
613
|
-
|
638
|
+
return_type = @return_type_expr || @resolver_class.type_expr
|
639
|
+
if return_type.nil?
|
640
|
+
raise MissingReturnTypeError, "Can't determine the return type for #{self.path} (it has `resolver: #{@resolver_class}`, perhaps that class is missing a `type ...` declaration, or perhaps its type causes a cyclical loading issue)"
|
641
|
+
end
|
642
|
+
nullable = @return_type_null.nil? ? @resolver_class.null : @return_type_null
|
643
|
+
Member::BuildType.parse_type(return_type, null: nullable)
|
644
|
+
elsif !@return_type_expr.nil?
|
645
|
+
@type ||= Member::BuildType.parse_type(@return_type_expr, null: @return_type_null)
|
614
646
|
end
|
615
|
-
raise MissingReturnTypeError, message
|
616
647
|
else
|
617
|
-
|
648
|
+
@return_type_expr = new_type
|
649
|
+
# If `type` is set in the definition block, then the `connection_extension: ...` given as a keyword won't be used, hmm...
|
650
|
+
# Also, arguments added by `connection_extension` will clobber anything previously defined,
|
651
|
+
# so `type(...)` should go first.
|
652
|
+
set_pagination_extensions(connection_extension: self.class.connection_extension)
|
618
653
|
end
|
619
654
|
rescue GraphQL::Schema::InvalidDocumentError, MissingReturnTypeError => err
|
620
655
|
# Let this propagate up
|
@@ -631,29 +666,22 @@ module GraphQL
|
|
631
666
|
end
|
632
667
|
end
|
633
668
|
|
634
|
-
def accessible?(context)
|
635
|
-
if @resolver_class
|
636
|
-
@resolver_class.accessible?(context)
|
637
|
-
else
|
638
|
-
true
|
639
|
-
end
|
640
|
-
end
|
641
|
-
|
642
669
|
def authorized?(object, args, context)
|
643
670
|
if @resolver_class
|
644
671
|
# The resolver _instance_ will check itself during `resolve()`
|
645
672
|
@resolver_class.authorized?(object, context)
|
646
673
|
else
|
647
|
-
if (arg_values = context[:current_arguments])
|
648
|
-
# ^^ that's provided by the interpreter at runtime, and includes info about whether the default value was used or not.
|
649
|
-
using_arg_values = true
|
650
|
-
arg_values = arg_values.argument_values
|
651
|
-
else
|
652
|
-
arg_values = args
|
653
|
-
using_arg_values = false
|
654
|
-
end
|
655
674
|
if args.size > 0
|
656
|
-
|
675
|
+
if (arg_values = context[:current_arguments])
|
676
|
+
# ^^ that's provided by the interpreter at runtime, and includes info about whether the default value was used or not.
|
677
|
+
using_arg_values = true
|
678
|
+
arg_values = arg_values.argument_values
|
679
|
+
else
|
680
|
+
arg_values = args
|
681
|
+
using_arg_values = false
|
682
|
+
end
|
683
|
+
|
684
|
+
args = context.types.arguments(self)
|
657
685
|
args.each do |arg|
|
658
686
|
arg_key = arg.keyword
|
659
687
|
if arg_values.key?(arg_key)
|
@@ -682,70 +710,117 @@ module GraphQL
|
|
682
710
|
end
|
683
711
|
end
|
684
712
|
|
685
|
-
# Implement {GraphQL::Field}'s resolve API.
|
686
|
-
#
|
687
|
-
# Eventually, we might hook up field instances to execution in another way. TBD.
|
688
|
-
# @see #resolve for how the interpreter hooks up to it
|
689
|
-
def resolve_field(obj, args, ctx)
|
690
|
-
ctx.schema.after_lazy(obj) do |after_obj|
|
691
|
-
# First, apply auth ...
|
692
|
-
query_ctx = ctx.query.context
|
693
|
-
# Some legacy fields can have `nil` here, not exactly sure why.
|
694
|
-
# @see https://github.com/rmosolgo/graphql-ruby/issues/1990 before removing
|
695
|
-
inner_obj = after_obj && after_obj.object
|
696
|
-
ctx.schema.after_lazy(to_ruby_args(after_obj, args, ctx)) do |ruby_args|
|
697
|
-
if authorized?(inner_obj, ruby_args, query_ctx)
|
698
|
-
# Then if it passed, resolve the field
|
699
|
-
if @resolve_proc
|
700
|
-
# Might be nil, still want to call the func in that case
|
701
|
-
with_extensions(inner_obj, ruby_args, query_ctx) do |extended_obj, extended_args|
|
702
|
-
# Pass the GraphQL args here for compatibility:
|
703
|
-
@resolve_proc.call(extended_obj, args, ctx)
|
704
|
-
end
|
705
|
-
else
|
706
|
-
public_send_field(after_obj, ruby_args, query_ctx)
|
707
|
-
end
|
708
|
-
else
|
709
|
-
err = GraphQL::UnauthorizedFieldError.new(object: inner_obj, type: obj.class, context: ctx, field: self)
|
710
|
-
query_ctx.schema.unauthorized_field(err)
|
711
|
-
end
|
712
|
-
end
|
713
|
-
end
|
714
|
-
end
|
715
|
-
|
716
713
|
# This method is called by the interpreter for each field.
|
717
714
|
# You can extend it in your base field classes.
|
718
715
|
# @param object [GraphQL::Schema::Object] An instance of some type class, wrapping an application object
|
719
716
|
# @param args [Hash] A symbol-keyed hash of Ruby keyword arguments. (Empty if no args)
|
720
717
|
# @param ctx [GraphQL::Query::Context]
|
721
|
-
def resolve(object, args,
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
718
|
+
def resolve(object, args, query_ctx)
|
719
|
+
# Unwrap the GraphQL object to get the application object.
|
720
|
+
application_object = object.object
|
721
|
+
method_receiver = nil
|
722
|
+
method_to_call = nil
|
723
|
+
method_args = nil
|
724
|
+
|
725
|
+
@own_validators && Schema::Validator.validate!(validators, application_object, query_ctx, args)
|
726
|
+
|
727
|
+
query_ctx.query.after_lazy(self.authorized?(application_object, args, query_ctx)) do |is_authorized|
|
728
|
+
if is_authorized
|
729
|
+
with_extensions(object, args, query_ctx) do |obj, ruby_kwargs|
|
730
|
+
method_args = ruby_kwargs
|
731
|
+
if @resolver_class
|
732
|
+
if obj.is_a?(GraphQL::Schema::Object)
|
733
|
+
obj = obj.object
|
734
|
+
end
|
735
|
+
obj = @resolver_class.new(object: obj, context: query_ctx, field: self)
|
736
|
+
end
|
728
737
|
|
729
|
-
|
738
|
+
inner_object = obj.object
|
730
739
|
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
740
|
+
if !NOT_CONFIGURED.equal?(@hash_key)
|
741
|
+
hash_value = if inner_object.is_a?(Hash)
|
742
|
+
inner_object.key?(@hash_key) ? inner_object[@hash_key] : inner_object[@hash_key_str]
|
743
|
+
elsif inner_object.respond_to?(:[])
|
744
|
+
inner_object[@hash_key]
|
745
|
+
else
|
746
|
+
nil
|
747
|
+
end
|
748
|
+
if hash_value == false
|
749
|
+
hash_value
|
750
|
+
else
|
751
|
+
hash_value || (@fallback_value != NOT_CONFIGURED ? @fallback_value : nil)
|
752
|
+
end
|
753
|
+
elsif obj.respond_to?(resolver_method)
|
754
|
+
method_to_call = resolver_method
|
755
|
+
method_receiver = obj
|
756
|
+
# Call the method with kwargs, if there are any
|
757
|
+
if !ruby_kwargs.empty?
|
758
|
+
obj.public_send(resolver_method, **ruby_kwargs)
|
759
|
+
else
|
760
|
+
obj.public_send(resolver_method)
|
761
|
+
end
|
762
|
+
elsif inner_object.is_a?(Hash)
|
763
|
+
if @dig_keys
|
764
|
+
inner_object.dig(*@dig_keys)
|
765
|
+
elsif inner_object.key?(@method_sym)
|
766
|
+
inner_object[@method_sym]
|
767
|
+
elsif inner_object.key?(@method_str) || !inner_object.default_proc.nil?
|
768
|
+
inner_object[@method_str]
|
769
|
+
elsif @fallback_value != NOT_CONFIGURED
|
770
|
+
@fallback_value
|
771
|
+
else
|
772
|
+
nil
|
773
|
+
end
|
774
|
+
elsif inner_object.respond_to?(@method_sym)
|
775
|
+
method_to_call = @method_sym
|
776
|
+
method_receiver = obj.object
|
777
|
+
if !ruby_kwargs.empty?
|
778
|
+
inner_object.public_send(@method_sym, **ruby_kwargs)
|
779
|
+
else
|
780
|
+
inner_object.public_send(@method_sym)
|
781
|
+
end
|
782
|
+
elsif @fallback_value != NOT_CONFIGURED
|
783
|
+
@fallback_value
|
784
|
+
else
|
785
|
+
raise <<-ERR
|
786
|
+
Failed to implement #{@owner.graphql_name}.#{@name}, tried:
|
787
|
+
|
788
|
+
- `#{obj.class}##{resolver_method}`, which did not exist
|
789
|
+
- `#{inner_object.class}##{@method_sym}`, which did not exist
|
790
|
+
- Looking up hash key `#{@method_sym.inspect}` or `#{@method_str.inspect}` on `#{inner_object}`, but it wasn't a Hash
|
791
|
+
|
792
|
+
To implement this field, define one of the methods above (and check for typos), or supply a `fallback_value`.
|
793
|
+
ERR
|
794
|
+
end
|
736
795
|
end
|
796
|
+
else
|
797
|
+
raise GraphQL::UnauthorizedFieldError.new(object: application_object, type: object.class, context: query_ctx, field: self)
|
737
798
|
end
|
738
|
-
rescue GraphQL::UnauthorizedFieldError => err
|
739
|
-
err.field ||= self
|
740
|
-
ctx.schema.unauthorized_field(err)
|
741
|
-
rescue GraphQL::UnauthorizedError => err
|
742
|
-
ctx.schema.unauthorized_object(err)
|
743
799
|
end
|
800
|
+
rescue GraphQL::UnauthorizedFieldError => err
|
801
|
+
err.field ||= self
|
802
|
+
begin
|
803
|
+
query_ctx.schema.unauthorized_field(err)
|
804
|
+
rescue GraphQL::ExecutionError => err
|
805
|
+
err
|
806
|
+
end
|
807
|
+
rescue GraphQL::UnauthorizedError => err
|
808
|
+
begin
|
809
|
+
query_ctx.schema.unauthorized_object(err)
|
810
|
+
rescue GraphQL::ExecutionError => err
|
811
|
+
err
|
812
|
+
end
|
813
|
+
rescue ArgumentError
|
814
|
+
if method_receiver && method_to_call
|
815
|
+
assert_satisfactory_implementation(method_receiver, method_to_call, method_args)
|
816
|
+
end
|
817
|
+
# if the line above doesn't raise, re-raise
|
818
|
+
raise
|
744
819
|
rescue GraphQL::ExecutionError => err
|
745
820
|
err
|
746
821
|
end
|
747
822
|
|
748
|
-
# @param ctx [GraphQL::Query::Context
|
823
|
+
# @param ctx [GraphQL::Query::Context]
|
749
824
|
def fetch_extra(extra_name, ctx)
|
750
825
|
if extra_name != :path && extra_name != :ast_node && respond_to?(extra_name)
|
751
826
|
self.public_send(extra_name)
|
@@ -758,129 +833,6 @@ module GraphQL
|
|
758
833
|
|
759
834
|
private
|
760
835
|
|
761
|
-
NO_ARGS = {}.freeze
|
762
|
-
|
763
|
-
# Convert a GraphQL arguments instance into a Ruby-style hash.
|
764
|
-
#
|
765
|
-
# @param obj [GraphQL::Schema::Object] The object where this field is being resolved
|
766
|
-
# @param graphql_args [GraphQL::Query::Arguments]
|
767
|
-
# @param field_ctx [GraphQL::Query::Context::FieldResolutionContext]
|
768
|
-
# @return [Hash<Symbol => Any>]
|
769
|
-
def to_ruby_args(obj, graphql_args, field_ctx)
|
770
|
-
if graphql_args.any? || @extras.any?
|
771
|
-
# Splat the GraphQL::Arguments to Ruby keyword arguments
|
772
|
-
ruby_kwargs = graphql_args.to_kwargs
|
773
|
-
maybe_lazies = []
|
774
|
-
# Apply any `prepare` methods. Not great code organization, can this go somewhere better?
|
775
|
-
arguments(field_ctx).each do |name, arg_defn|
|
776
|
-
ruby_kwargs_key = arg_defn.keyword
|
777
|
-
|
778
|
-
if ruby_kwargs.key?(ruby_kwargs_key)
|
779
|
-
loads = arg_defn.loads
|
780
|
-
value = ruby_kwargs[ruby_kwargs_key]
|
781
|
-
loaded_value = if loads && !arg_defn.from_resolver?
|
782
|
-
if arg_defn.type.list?
|
783
|
-
loaded_values = value.map { |val| load_application_object(arg_defn, loads, val, field_ctx.query.context) }
|
784
|
-
field_ctx.schema.after_any_lazies(loaded_values) { |result| result }
|
785
|
-
else
|
786
|
-
load_application_object(arg_defn, loads, value, field_ctx.query.context)
|
787
|
-
end
|
788
|
-
elsif arg_defn.type.list? && value.is_a?(Array)
|
789
|
-
field_ctx.schema.after_any_lazies(value, &:itself)
|
790
|
-
else
|
791
|
-
value
|
792
|
-
end
|
793
|
-
|
794
|
-
maybe_lazies << field_ctx.schema.after_lazy(loaded_value) do |loaded_value|
|
795
|
-
prepared_value = if arg_defn.prepare
|
796
|
-
arg_defn.prepare_value(obj, loaded_value)
|
797
|
-
else
|
798
|
-
loaded_value
|
799
|
-
end
|
800
|
-
|
801
|
-
ruby_kwargs[ruby_kwargs_key] = prepared_value
|
802
|
-
end
|
803
|
-
end
|
804
|
-
end
|
805
|
-
|
806
|
-
@extras.each do |extra_arg|
|
807
|
-
ruby_kwargs[extra_arg] = fetch_extra(extra_arg, field_ctx)
|
808
|
-
end
|
809
|
-
|
810
|
-
field_ctx.schema.after_any_lazies(maybe_lazies) do
|
811
|
-
ruby_kwargs
|
812
|
-
end
|
813
|
-
else
|
814
|
-
NO_ARGS
|
815
|
-
end
|
816
|
-
end
|
817
|
-
|
818
|
-
def public_send_field(unextended_obj, unextended_ruby_kwargs, query_ctx)
|
819
|
-
with_extensions(unextended_obj, unextended_ruby_kwargs, query_ctx) do |obj, ruby_kwargs|
|
820
|
-
begin
|
821
|
-
method_receiver = nil
|
822
|
-
method_to_call = nil
|
823
|
-
if @resolver_class
|
824
|
-
if obj.is_a?(GraphQL::Schema::Object)
|
825
|
-
obj = obj.object
|
826
|
-
end
|
827
|
-
obj = @resolver_class.new(object: obj, context: query_ctx, field: self)
|
828
|
-
end
|
829
|
-
|
830
|
-
# Find a way to resolve this field, checking:
|
831
|
-
#
|
832
|
-
# - A method on the type instance;
|
833
|
-
# - Hash keys, if the wrapped object is a hash or responds to `#[]`
|
834
|
-
# - A method on the wrapped object;
|
835
|
-
# - Or, raise not implemented.
|
836
|
-
#
|
837
|
-
if obj.respond_to?(@resolver_method)
|
838
|
-
method_to_call = @resolver_method
|
839
|
-
method_receiver = obj
|
840
|
-
# Call the method with kwargs, if there are any
|
841
|
-
if ruby_kwargs.any?
|
842
|
-
obj.public_send(@resolver_method, **ruby_kwargs)
|
843
|
-
else
|
844
|
-
obj.public_send(@resolver_method)
|
845
|
-
end
|
846
|
-
elsif obj.object.is_a?(Hash)
|
847
|
-
inner_object = obj.object
|
848
|
-
if @dig_keys
|
849
|
-
inner_object.dig(*@dig_keys)
|
850
|
-
elsif inner_object.key?(@method_sym)
|
851
|
-
inner_object[@method_sym]
|
852
|
-
else
|
853
|
-
inner_object[@method_str]
|
854
|
-
end
|
855
|
-
elsif defined?(@hash_key) && obj.object.respond_to?(:[])
|
856
|
-
obj.object[@hash_key]
|
857
|
-
elsif obj.object.respond_to?(@method_sym)
|
858
|
-
method_to_call = @method_sym
|
859
|
-
method_receiver = obj.object
|
860
|
-
if ruby_kwargs.any?
|
861
|
-
obj.object.public_send(@method_sym, **ruby_kwargs)
|
862
|
-
else
|
863
|
-
obj.object.public_send(@method_sym)
|
864
|
-
end
|
865
|
-
else
|
866
|
-
raise <<-ERR
|
867
|
-
Failed to implement #{@owner.graphql_name}.#{@name}, tried:
|
868
|
-
|
869
|
-
- `#{obj.class}##{@resolver_method}`, which did not exist
|
870
|
-
- `#{obj.object.class}##{@method_sym}`, which did not exist
|
871
|
-
- Looking up hash key `#{@method_sym.inspect}` or `#{@method_str.inspect}` on `#{obj.object}`, but it wasn't a Hash
|
872
|
-
|
873
|
-
To implement this field, define one of the methods above (and check for typos)
|
874
|
-
ERR
|
875
|
-
end
|
876
|
-
rescue ArgumentError
|
877
|
-
assert_satisfactory_implementation(method_receiver, method_to_call, ruby_kwargs)
|
878
|
-
# if the line above doesn't raise, re-raise
|
879
|
-
raise
|
880
|
-
end
|
881
|
-
end
|
882
|
-
end
|
883
|
-
|
884
836
|
def assert_satisfactory_implementation(receiver, method_name, ruby_kwargs)
|
885
837
|
method_defn = receiver.method(method_name)
|
886
838
|
unsatisfied_ruby_kwargs = ruby_kwargs.dup
|
@@ -909,9 +861,9 @@ module GraphQL
|
|
909
861
|
unsatisfied_ruby_kwargs.clear
|
910
862
|
end
|
911
863
|
|
912
|
-
if unsatisfied_ruby_kwargs.
|
864
|
+
if !unsatisfied_ruby_kwargs.empty? || !unsatisfied_method_params.empty?
|
913
865
|
raise FieldImplementationFailed.new, <<-ERR
|
914
|
-
Failed to call
|
866
|
+
Failed to call `#{method_name.inspect}` on #{receiver.inspect} because the Ruby method params were incompatible with the GraphQL arguments:
|
915
867
|
|
916
868
|
#{ unsatisfied_ruby_kwargs
|
917
869
|
.map { |key, value| "- `#{key}: #{value}` was given by GraphQL but not defined in the Ruby method. Add `#{key}:` to the method parameters." }
|
@@ -921,6 +873,17 @@ ERR
|
|
921
873
|
end
|
922
874
|
end
|
923
875
|
|
876
|
+
class ExtendedState
|
877
|
+
def initialize(args, object)
|
878
|
+
@arguments = args
|
879
|
+
@object = object
|
880
|
+
@memos = nil
|
881
|
+
@added_extras = nil
|
882
|
+
end
|
883
|
+
|
884
|
+
attr_accessor :arguments, :object, :memos, :added_extras
|
885
|
+
end
|
886
|
+
|
924
887
|
# Wrap execution with hooks.
|
925
888
|
# Written iteratively to avoid big stack traces.
|
926
889
|
# @return [Object] Whatever the
|
@@ -931,20 +894,20 @@ ERR
|
|
931
894
|
# This is a hack to get the _last_ value for extended obj and args,
|
932
895
|
# in case one of the extensions doesn't `yield`.
|
933
896
|
# (There's another implementation that uses multiple-return, but I'm wary of the perf cost of the extra arrays)
|
934
|
-
extended =
|
897
|
+
extended = ExtendedState.new(args, obj)
|
935
898
|
value = run_extensions_before_resolve(obj, args, ctx, extended) do |obj, args|
|
936
|
-
if (added_extras = extended
|
899
|
+
if (added_extras = extended.added_extras)
|
937
900
|
args = args.dup
|
938
901
|
added_extras.each { |e| args.delete(e) }
|
939
902
|
end
|
940
903
|
yield(obj, args)
|
941
904
|
end
|
942
905
|
|
943
|
-
extended_obj = extended
|
944
|
-
extended_args = extended
|
945
|
-
memos = extended
|
906
|
+
extended_obj = extended.object
|
907
|
+
extended_args = extended.arguments # rubocop:disable Development/ContextIsPassedCop
|
908
|
+
memos = extended.memos || EMPTY_HASH
|
946
909
|
|
947
|
-
ctx.
|
910
|
+
ctx.query.after_lazy(value) do |resolved_value|
|
948
911
|
idx = 0
|
949
912
|
@extensions.each do |ext|
|
950
913
|
memo = memos[idx]
|
@@ -962,23 +925,55 @@ ERR
|
|
962
925
|
if extension
|
963
926
|
extension.resolve(object: obj, arguments: args, context: ctx) do |extended_obj, extended_args, memo|
|
964
927
|
if memo
|
965
|
-
memos = extended
|
928
|
+
memos = extended.memos ||= {}
|
966
929
|
memos[idx] = memo
|
967
930
|
end
|
968
931
|
|
969
932
|
if (extras = extension.added_extras)
|
970
|
-
ae = extended
|
933
|
+
ae = extended.added_extras ||= []
|
971
934
|
ae.concat(extras)
|
972
935
|
end
|
973
936
|
|
974
|
-
extended
|
975
|
-
extended
|
937
|
+
extended.object = extended_obj
|
938
|
+
extended.arguments = extended_args
|
976
939
|
run_extensions_before_resolve(extended_obj, extended_args, ctx, extended, idx: idx + 1) { |o, a| yield(o, a) }
|
977
940
|
end
|
978
941
|
else
|
979
942
|
yield(obj, args)
|
980
943
|
end
|
981
944
|
end
|
945
|
+
|
946
|
+
def apply_own_complexity_to(child_complexity, query, nodes)
|
947
|
+
case (own_complexity = complexity)
|
948
|
+
when Numeric
|
949
|
+
own_complexity + child_complexity
|
950
|
+
when Proc
|
951
|
+
arguments = query.arguments_for(nodes.first, self)
|
952
|
+
if arguments.is_a?(GraphQL::ExecutionError)
|
953
|
+
return child_complexity
|
954
|
+
elsif arguments.respond_to?(:keyword_arguments)
|
955
|
+
arguments = arguments.keyword_arguments
|
956
|
+
end
|
957
|
+
|
958
|
+
own_complexity.call(query.context, arguments, child_complexity)
|
959
|
+
else
|
960
|
+
raise ArgumentError, "Invalid complexity for #{self.path}: #{own_complexity.inspect}"
|
961
|
+
end
|
962
|
+
end
|
963
|
+
|
964
|
+
def set_pagination_extensions(connection_extension:)
|
965
|
+
# This should run before connection extension,
|
966
|
+
# but should it run after the definition block?
|
967
|
+
if scoped?
|
968
|
+
self.extension(ScopeExtension, call_after_define: false)
|
969
|
+
end
|
970
|
+
|
971
|
+
# The problem with putting this after the definition_block
|
972
|
+
# is that it would override arguments
|
973
|
+
if connection? && connection_extension
|
974
|
+
self.extension(connection_extension, call_after_define: false)
|
975
|
+
end
|
976
|
+
end
|
982
977
|
end
|
983
978
|
end
|
984
979
|
end
|