graphql 2.0.32 → 2.5.22
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/detailed_trace_generator.rb +77 -0
- 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 +49 -0
- data/lib/generators/graphql/orm_mutations_base.rb +1 -1
- 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/create_graphql_detailed_traces.erb +10 -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 +5 -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 +82 -0
- data/lib/graphql/analysis/max_query_complexity.rb +20 -0
- data/lib/graphql/analysis/max_query_depth.rb +20 -0
- data/lib/graphql/analysis/query_complexity.rb +263 -0
- data/lib/graphql/analysis/query_depth.rb +58 -0
- data/lib/graphql/analysis/visitor.rb +280 -0
- data/lib/graphql/analysis.rb +95 -1
- data/lib/graphql/autoload.rb +38 -0
- data/lib/graphql/backtrace/table.rb +118 -55
- data/lib/graphql/backtrace.rb +1 -19
- data/lib/graphql/coercion_error.rb +1 -9
- data/lib/graphql/current.rb +57 -0
- data/lib/graphql/dashboard/application_controller.rb +41 -0
- data/lib/graphql/dashboard/detailed_traces.rb +47 -0
- data/lib/graphql/dashboard/installable.rb +22 -0
- data/lib/graphql/dashboard/landings_controller.rb +9 -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/statics_controller.rb +31 -0
- data/lib/graphql/dashboard/subscriptions.rb +97 -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 +24 -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 +96 -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 +112 -0
- data/lib/graphql/dataloader/null_dataloader.rb +55 -10
- data/lib/graphql/dataloader/request.rb +5 -0
- data/lib/graphql/dataloader/source.rb +35 -12
- data/lib/graphql/dataloader.rb +224 -149
- data/lib/graphql/date_encoding_error.rb +1 -1
- data/lib/graphql/dig.rb +2 -1
- data/lib/graphql/duration_encoding_error.rb +16 -0
- data/lib/graphql/execution/interpreter/argument_value.rb +5 -1
- data/lib/graphql/execution/interpreter/arguments_cache.rb +5 -10
- data/lib/graphql/execution/interpreter/resolve.rb +23 -25
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +228 -0
- data/lib/graphql/execution/interpreter/runtime.rb +363 -434
- data/lib/graphql/execution/interpreter.rb +91 -164
- data/lib/graphql/execution/lookahead.rb +105 -31
- data/lib/graphql/execution/multiplex.rb +7 -6
- data/lib/graphql/execution/next/field_resolve_step.rb +711 -0
- data/lib/graphql/execution/next/load_argument_step.rb +60 -0
- data/lib/graphql/execution/next/prepare_object_step.rb +129 -0
- data/lib/graphql/execution/next/runner.rb +389 -0
- data/lib/graphql/execution/next/selections_step.rb +37 -0
- data/lib/graphql/execution/next.rb +70 -0
- data/lib/graphql/execution.rb +1 -0
- data/lib/graphql/execution_error.rb +13 -10
- data/lib/graphql/introspection/directive_location_enum.rb +1 -1
- data/lib/graphql/introspection/directive_type.rb +7 -3
- data/lib/graphql/introspection/dynamic_fields.rb +5 -1
- data/lib/graphql/introspection/entry_points.rb +20 -6
- data/lib/graphql/introspection/enum_value_type.rb +5 -5
- data/lib/graphql/introspection/field_type.rb +13 -5
- data/lib/graphql/introspection/input_value_type.rb +21 -13
- data/lib/graphql/introspection/schema_type.rb +8 -11
- data/lib/graphql/introspection/type_type.rb +64 -28
- data/lib/graphql/invalid_name_error.rb +1 -1
- data/lib/graphql/invalid_null_error.rb +26 -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 +90 -61
- data/lib/graphql/language/lexer.rb +319 -193
- data/lib/graphql/language/nodes.rb +136 -77
- data/lib/graphql/language/parser.rb +807 -1985
- data/lib/graphql/language/printer.rb +324 -151
- data/lib/graphql/language/sanitized_printer.rb +21 -23
- data/lib/graphql/language/static_visitor.rb +171 -0
- data/lib/graphql/language/visitor.rb +23 -83
- data/lib/graphql/language.rb +71 -1
- data/lib/graphql/load_application_object_failed_error.rb +5 -1
- data/lib/graphql/pagination/array_connection.rb +6 -6
- data/lib/graphql/pagination/connection.rb +30 -1
- data/lib/graphql/pagination/connections.rb +32 -0
- data/lib/graphql/pagination/mongoid_relation_connection.rb +1 -2
- data/lib/graphql/query/context/scoped_context.rb +101 -0
- data/lib/graphql/query/context.rb +82 -144
- data/lib/graphql/query/null_context.rb +15 -18
- data/lib/graphql/query/partial.rb +179 -0
- data/lib/graphql/query/validation_pipeline.rb +4 -4
- data/lib/graphql/query/variable_validation_error.rb +1 -1
- data/lib/graphql/query/variables.rb +3 -3
- data/lib/graphql/query.rb +126 -81
- data/lib/graphql/railtie.rb +16 -6
- data/lib/graphql/rake_task.rb +3 -12
- 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 +26 -13
- data/lib/graphql/schema/always_visible.rb +7 -2
- data/lib/graphql/schema/argument.rb +75 -9
- data/lib/graphql/schema/base_64_encoder.rb +3 -5
- data/lib/graphql/schema/build_from_definition.rb +123 -60
- data/lib/graphql/schema/directive/flagged.rb +4 -2
- data/lib/graphql/schema/directive/one_of.rb +12 -0
- data/lib/graphql/schema/directive/specified_by.rb +14 -0
- data/lib/graphql/schema/directive.rb +54 -2
- data/lib/graphql/schema/enum.rb +110 -27
- data/lib/graphql/schema/enum_value.rb +10 -2
- data/lib/graphql/schema/field/connection_extension.rb +15 -49
- data/lib/graphql/schema/field/scope_extension.rb +23 -7
- data/lib/graphql/schema/field.rb +245 -118
- data/lib/graphql/schema/field_extension.rb +34 -1
- data/lib/graphql/schema/has_single_input_argument.rb +160 -0
- data/lib/graphql/schema/input_object.rb +116 -60
- data/lib/graphql/schema/interface.rb +34 -16
- data/lib/graphql/schema/introspection_system.rb +8 -17
- data/lib/graphql/schema/late_bound_type.rb +4 -0
- data/lib/graphql/schema/list.rb +3 -3
- data/lib/graphql/schema/loader.rb +3 -4
- data/lib/graphql/schema/member/base_dsl_methods.rb +18 -2
- data/lib/graphql/schema/member/has_arguments.rb +132 -100
- data/lib/graphql/schema/member/has_authorization.rb +35 -0
- data/lib/graphql/schema/member/has_dataloader.rb +99 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +15 -0
- data/lib/graphql/schema/member/has_directives.rb +4 -4
- data/lib/graphql/schema/member/has_fields.rb +115 -15
- data/lib/graphql/schema/member/has_interfaces.rb +26 -12
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +5 -1
- data/lib/graphql/schema/member/has_validators.rb +1 -1
- data/lib/graphql/schema/member/relay_shortcuts.rb +1 -1
- data/lib/graphql/schema/member/scoped.rb +19 -0
- data/lib/graphql/schema/member/type_system_helpers.rb +17 -4
- data/lib/graphql/schema/member/validates_input.rb +3 -3
- data/lib/graphql/schema/member.rb +6 -0
- data/lib/graphql/schema/mutation.rb +7 -0
- data/lib/graphql/schema/object.rb +34 -8
- data/lib/graphql/schema/printer.rb +9 -7
- data/lib/graphql/schema/ractor_shareable.rb +79 -0
- data/lib/graphql/schema/relay_classic_mutation.rb +6 -129
- data/lib/graphql/schema/resolver.rb +90 -32
- data/lib/graphql/schema/scalar.rb +4 -9
- data/lib/graphql/schema/subscription.rb +63 -10
- data/lib/graphql/schema/timeout.rb +19 -2
- data/lib/graphql/schema/type_expression.rb +2 -2
- data/lib/graphql/schema/union.rb +2 -2
- 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 +92 -11
- data/lib/graphql/schema/validator.rb +3 -1
- 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 +275 -103
- data/lib/graphql/schema.rb +950 -210
- data/lib/graphql/static_validation/all_rules.rb +3 -3
- data/lib/graphql/static_validation/base_visitor.rb +7 -6
- data/lib/graphql/static_validation/literal_validator.rb +6 -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 +3 -3
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +2 -0
- 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 +47 -13
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +88 -25
- 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/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 +7 -3
- 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 +9 -1
- data/lib/graphql/static_validation.rb +0 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +8 -5
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +11 -5
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +12 -10
- data/lib/graphql/subscriptions/event.rb +21 -4
- data/lib/graphql/subscriptions/serialize.rb +3 -1
- data/lib/graphql/subscriptions.rb +21 -17
- data/lib/graphql/testing/helpers.rb +161 -0
- data/lib/graphql/testing/mock_action_cable.rb +111 -0
- data/lib/graphql/testing.rb +3 -0
- data/lib/graphql/tracing/active_support_notifications_trace.rb +14 -3
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +1 -1
- data/lib/graphql/tracing/appoptics_trace.rb +7 -3
- data/lib/graphql/tracing/appoptics_tracing.rb +9 -2
- data/lib/graphql/tracing/appsignal_trace.rb +32 -59
- 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 +46 -162
- data/lib/graphql/tracing/data_dog_tracing.rb +2 -0
- data/lib/graphql/tracing/detailed_trace/active_record_backend.rb +74 -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 +156 -0
- data/lib/graphql/tracing/legacy_hooks_trace.rb +75 -0
- data/lib/graphql/tracing/legacy_trace.rb +4 -61
- data/lib/graphql/tracing/monitor_trace.rb +283 -0
- data/lib/graphql/tracing/new_relic_trace.rb +47 -54
- data/lib/graphql/tracing/new_relic_tracing.rb +2 -0
- data/lib/graphql/tracing/notifications_trace.rb +183 -37
- 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 +864 -0
- data/lib/graphql/tracing/platform_tracing.rb +3 -1
- data/lib/graphql/tracing/{prometheus_tracing → prometheus_trace}/graphql_collector.rb +5 -1
- data/lib/graphql/tracing/prometheus_trace.rb +73 -73
- data/lib/graphql/tracing/prometheus_tracing.rb +2 -0
- data/lib/graphql/tracing/scout_trace.rb +32 -58
- data/lib/graphql/tracing/scout_tracing.rb +2 -0
- data/lib/graphql/tracing/sentry_trace.rb +82 -0
- data/lib/graphql/tracing/statsd_trace.rb +33 -45
- data/lib/graphql/tracing/statsd_tracing.rb +2 -0
- data/lib/graphql/tracing/trace.rb +112 -1
- data/lib/graphql/tracing.rb +31 -28
- data/lib/graphql/type_kinds.rb +2 -1
- data/lib/graphql/types/iso_8601_duration.rb +77 -0
- data/lib/graphql/types/relay/connection_behaviors.rb +44 -2
- data/lib/graphql/types/relay/edge_behaviors.rb +18 -0
- data/lib/graphql/types/relay/has_node_field.rb +13 -8
- data/lib/graphql/types/relay/has_nodes_field.rb +13 -8
- data/lib/graphql/types/relay/node_behaviors.rb +13 -2
- data/lib/graphql/types/relay/page_info_behaviors.rb +4 -0
- data/lib/graphql/types.rb +18 -10
- data/lib/graphql/unauthorized_enum_value_error.rb +13 -0
- data/lib/graphql/unauthorized_error.rb +5 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +71 -54
- data/readme.md +12 -2
- metadata +233 -37
- data/lib/graphql/analysis/ast/analyzer.rb +0 -84
- data/lib/graphql/analysis/ast/field_usage.rb +0 -57
- data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -22
- 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 -55
- data/lib/graphql/analysis/ast/visitor.rb +0 -276
- data/lib/graphql/analysis/ast.rb +0 -81
- data/lib/graphql/backtrace/inspect_result.rb +0 -50
- data/lib/graphql/backtrace/trace.rb +0 -96
- data/lib/graphql/backtrace/tracer.rb +0 -80
- data/lib/graphql/deprecation.rb +0 -9
- data/lib/graphql/filter.rb +0 -59
- data/lib/graphql/language/parser.y +0 -560
- data/lib/graphql/language/token.rb +0 -34
- data/lib/graphql/schema/base_64_bp.rb +0 -26
- data/lib/graphql/schema/invalid_type_error.rb +0 -7
- data/lib/graphql/schema/null_mask.rb +0 -11
- 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/subscriptions/instrumentation.rb +0 -28
|
@@ -83,6 +83,38 @@ module GraphQL
|
|
|
83
83
|
end
|
|
84
84
|
end
|
|
85
85
|
|
|
86
|
+
def populate_connection(field, object, value, original_arguments, context)
|
|
87
|
+
if value.is_a? GraphQL::ExecutionError
|
|
88
|
+
# This isn't even going to work because context doesn't have ast_node anymore
|
|
89
|
+
context.add_error(value)
|
|
90
|
+
nil
|
|
91
|
+
elsif value.nil?
|
|
92
|
+
nil
|
|
93
|
+
elsif value.is_a?(GraphQL::Pagination::Connection)
|
|
94
|
+
# update the connection with some things that may not have been provided
|
|
95
|
+
value.context ||= context
|
|
96
|
+
value.parent ||= object
|
|
97
|
+
value.first_value ||= original_arguments[:first]
|
|
98
|
+
value.after_value ||= original_arguments[:after]
|
|
99
|
+
value.last_value ||= original_arguments[:last]
|
|
100
|
+
value.before_value ||= original_arguments[:before]
|
|
101
|
+
value.arguments ||= original_arguments # rubocop:disable Development/ContextIsPassedCop -- unrelated .arguments method
|
|
102
|
+
value.field ||= field
|
|
103
|
+
if field.has_max_page_size? && !value.has_max_page_size_override?
|
|
104
|
+
value.max_page_size = field.max_page_size
|
|
105
|
+
end
|
|
106
|
+
if field.has_default_page_size? && !value.has_default_page_size_override?
|
|
107
|
+
value.default_page_size = field.default_page_size
|
|
108
|
+
end
|
|
109
|
+
if (custom_t = context.schema.connections.edge_class_for_field(field))
|
|
110
|
+
value.edge_class = custom_t
|
|
111
|
+
end
|
|
112
|
+
value
|
|
113
|
+
else
|
|
114
|
+
context.namespace(:connections)[:all_wrappers] ||= context.schema.connections.all_wrappers
|
|
115
|
+
context.schema.connections.wrap(field, object, value, original_arguments, context)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
86
118
|
# use an override if there is one
|
|
87
119
|
# @api private
|
|
88
120
|
def edge_class_for_field(field)
|
|
@@ -13,8 +13,7 @@ module GraphQL
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def relation_count(relation)
|
|
16
|
-
|
|
17
|
-
relation.to_a.count
|
|
16
|
+
relation.all.count(relation.options.slice(:limit, :skip))
|
|
18
17
|
end
|
|
19
18
|
|
|
20
19
|
def null_relation(relation)
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module GraphQL
|
|
3
|
+
class Query
|
|
4
|
+
class Context
|
|
5
|
+
class ScopedContext
|
|
6
|
+
def initialize(query_context)
|
|
7
|
+
@query_context = query_context
|
|
8
|
+
@scoped_contexts = nil
|
|
9
|
+
@all_keys = nil
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def merged_context
|
|
13
|
+
if @scoped_contexts.nil?
|
|
14
|
+
GraphQL::EmptyObjects::EMPTY_HASH
|
|
15
|
+
else
|
|
16
|
+
merged_ctx = {}
|
|
17
|
+
each_present_path_ctx do |path_ctx|
|
|
18
|
+
merged_ctx = path_ctx.merge(merged_ctx)
|
|
19
|
+
end
|
|
20
|
+
merged_ctx
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def merge!(hash, at: current_path)
|
|
25
|
+
@all_keys ||= Set.new
|
|
26
|
+
@all_keys.merge(hash.keys)
|
|
27
|
+
ctx = @scoped_contexts ||= {}
|
|
28
|
+
at.each do |path_part|
|
|
29
|
+
ctx = ctx[path_part] ||= { parent: ctx }
|
|
30
|
+
end
|
|
31
|
+
this_scoped_ctx = ctx[:scoped_context] ||= {}
|
|
32
|
+
this_scoped_ctx.merge!(hash)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def key?(key)
|
|
36
|
+
if @all_keys && @all_keys.include?(key)
|
|
37
|
+
each_present_path_ctx do |path_ctx|
|
|
38
|
+
if path_ctx.key?(key)
|
|
39
|
+
return true
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
false
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def [](key)
|
|
47
|
+
each_present_path_ctx do |path_ctx|
|
|
48
|
+
if path_ctx.key?(key)
|
|
49
|
+
return path_ctx[key]
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
nil
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def current_path
|
|
56
|
+
@query_context.current_path || GraphQL::EmptyObjects::EMPTY_ARRAY
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def dig(key, *other_keys)
|
|
60
|
+
each_present_path_ctx do |path_ctx|
|
|
61
|
+
if path_ctx.key?(key)
|
|
62
|
+
found_value = path_ctx[key]
|
|
63
|
+
if !other_keys.empty?
|
|
64
|
+
return found_value.dig(*other_keys)
|
|
65
|
+
else
|
|
66
|
+
return found_value
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
nil
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
# Start at the current location,
|
|
76
|
+
# but look up the tree for previously-assigned scoped values
|
|
77
|
+
def each_present_path_ctx
|
|
78
|
+
ctx = @scoped_contexts
|
|
79
|
+
if ctx.nil?
|
|
80
|
+
# no-op
|
|
81
|
+
else
|
|
82
|
+
current_path.each do |path_part|
|
|
83
|
+
if ctx.key?(path_part)
|
|
84
|
+
ctx = ctx[path_part]
|
|
85
|
+
else
|
|
86
|
+
break
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
while ctx
|
|
91
|
+
if (scoped_ctx = ctx[:scoped_context])
|
|
92
|
+
yield(scoped_ctx)
|
|
93
|
+
end
|
|
94
|
+
ctx = ctx[:parent]
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -1,39 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
module GraphQL
|
|
3
4
|
class Query
|
|
4
5
|
# Expose some query-specific info to field resolve functions.
|
|
5
6
|
# It delegates `[]` to the hash that's passed to `GraphQL::Query#initialize`.
|
|
6
7
|
class Context
|
|
7
|
-
module SharedMethods
|
|
8
|
-
# Return this value to tell the runtime
|
|
9
|
-
# to exclude this field from the response altogether
|
|
10
|
-
def skip
|
|
11
|
-
GraphQL::Execution::SKIP
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# Add error at query-level.
|
|
15
|
-
# @param error [GraphQL::ExecutionError] an execution error
|
|
16
|
-
# @return [void]
|
|
17
|
-
def add_error(error)
|
|
18
|
-
if !error.is_a?(ExecutionError)
|
|
19
|
-
raise TypeError, "expected error to be a ExecutionError, but was #{error.class}"
|
|
20
|
-
end
|
|
21
|
-
errors << error
|
|
22
|
-
nil
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# @example Print the GraphQL backtrace during field resolution
|
|
26
|
-
# puts ctx.backtrace
|
|
27
|
-
#
|
|
28
|
-
# @return [GraphQL::Backtrace] The backtrace for this point in query execution
|
|
29
|
-
def backtrace
|
|
30
|
-
GraphQL::Backtrace.new(self)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def execution_errors
|
|
34
|
-
@execution_errors ||= ExecutionErrors.new(self)
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
8
|
|
|
38
9
|
class ExecutionErrors
|
|
39
10
|
def initialize(ctx)
|
|
@@ -57,8 +28,8 @@ module GraphQL
|
|
|
57
28
|
alias :push :add
|
|
58
29
|
end
|
|
59
30
|
|
|
60
|
-
include SharedMethods
|
|
61
31
|
extend Forwardable
|
|
32
|
+
include Schema::Member::HasDataloader
|
|
62
33
|
|
|
63
34
|
# @return [Array<GraphQL::ExecutionError>] errors returned during execution
|
|
64
35
|
attr_reader :errors
|
|
@@ -69,125 +40,21 @@ module GraphQL
|
|
|
69
40
|
# @return [GraphQL::Schema]
|
|
70
41
|
attr_reader :schema
|
|
71
42
|
|
|
72
|
-
# @return [Array<String, Integer>] The current position in the result
|
|
73
|
-
attr_reader :path
|
|
74
|
-
|
|
75
43
|
# Make a new context which delegates key lookup to `values`
|
|
76
44
|
# @param query [GraphQL::Query] the query who owns this context
|
|
77
45
|
# @param values [Hash] A hash of arbitrary values which will be accessible at query-time
|
|
78
|
-
def initialize(query:, schema: query.schema, values
|
|
46
|
+
def initialize(query:, schema: query.schema, values:)
|
|
79
47
|
@query = query
|
|
80
48
|
@schema = schema
|
|
81
49
|
@provided_values = values || {}
|
|
82
|
-
@object = object
|
|
83
50
|
# Namespaced storage, where user-provided values are in `nil` namespace:
|
|
84
51
|
@storage = Hash.new { |h, k| h[k] = {} }
|
|
85
52
|
@storage[nil] = @provided_values
|
|
86
53
|
@errors = []
|
|
87
|
-
@path = []
|
|
88
|
-
@value = nil
|
|
89
|
-
@context = self # for SharedMethods TODO delete sharedmethods
|
|
90
54
|
@scoped_context = ScopedContext.new(self)
|
|
91
55
|
end
|
|
92
56
|
|
|
93
|
-
|
|
94
|
-
NO_PATH = GraphQL::EmptyObjects::EMPTY_ARRAY
|
|
95
|
-
NO_CONTEXT = GraphQL::EmptyObjects::EMPTY_HASH
|
|
96
|
-
|
|
97
|
-
def initialize(query_context)
|
|
98
|
-
@query_context = query_context
|
|
99
|
-
@scoped_contexts = nil
|
|
100
|
-
@all_keys = nil
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def merged_context
|
|
104
|
-
if @scoped_contexts.nil?
|
|
105
|
-
NO_CONTEXT
|
|
106
|
-
else
|
|
107
|
-
merged_ctx = {}
|
|
108
|
-
each_present_path_ctx do |path_ctx|
|
|
109
|
-
merged_ctx = path_ctx.merge(merged_ctx)
|
|
110
|
-
end
|
|
111
|
-
merged_ctx
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
def merge!(hash)
|
|
116
|
-
@all_keys ||= Set.new
|
|
117
|
-
@all_keys.merge(hash.keys)
|
|
118
|
-
ctx = @scoped_contexts ||= {}
|
|
119
|
-
current_path.each do |path_part|
|
|
120
|
-
ctx = ctx[path_part] ||= { parent: ctx }
|
|
121
|
-
end
|
|
122
|
-
this_scoped_ctx = ctx[:scoped_context] ||= {}
|
|
123
|
-
this_scoped_ctx.merge!(hash)
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
def key?(key)
|
|
127
|
-
if @all_keys && @all_keys.include?(key)
|
|
128
|
-
each_present_path_ctx do |path_ctx|
|
|
129
|
-
if path_ctx.key?(key)
|
|
130
|
-
return true
|
|
131
|
-
end
|
|
132
|
-
end
|
|
133
|
-
end
|
|
134
|
-
false
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
def [](key)
|
|
138
|
-
each_present_path_ctx do |path_ctx|
|
|
139
|
-
if path_ctx.key?(key)
|
|
140
|
-
return path_ctx[key]
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
nil
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
def current_path
|
|
147
|
-
@query_context.current_path || NO_PATH
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
def dig(key, *other_keys)
|
|
151
|
-
each_present_path_ctx do |path_ctx|
|
|
152
|
-
if path_ctx.key?(key)
|
|
153
|
-
found_value = path_ctx[key]
|
|
154
|
-
if other_keys.any?
|
|
155
|
-
return found_value.dig(*other_keys)
|
|
156
|
-
else
|
|
157
|
-
return found_value
|
|
158
|
-
end
|
|
159
|
-
end
|
|
160
|
-
end
|
|
161
|
-
nil
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
private
|
|
165
|
-
|
|
166
|
-
# Start at the current location,
|
|
167
|
-
# but look up the tree for previously-assigned scoped values
|
|
168
|
-
def each_present_path_ctx
|
|
169
|
-
ctx = @scoped_contexts
|
|
170
|
-
if ctx.nil?
|
|
171
|
-
# no-op
|
|
172
|
-
else
|
|
173
|
-
current_path.each do |path_part|
|
|
174
|
-
if ctx.key?(path_part)
|
|
175
|
-
ctx = ctx[path_part]
|
|
176
|
-
else
|
|
177
|
-
break
|
|
178
|
-
end
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
while ctx
|
|
182
|
-
if (scoped_ctx = ctx[:scoped_context])
|
|
183
|
-
yield(scoped_ctx)
|
|
184
|
-
end
|
|
185
|
-
ctx = ctx[:parent]
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
end
|
|
189
|
-
end
|
|
190
|
-
|
|
57
|
+
# Modify this hash to return extensions to client.
|
|
191
58
|
# @return [Hash] A hash that will be added verbatim to the result hash, as `"extensions" => { ... }`
|
|
192
59
|
def response_extensions
|
|
193
60
|
namespace(:__query_result_extensions__)
|
|
@@ -210,9 +77,15 @@ module GraphQL
|
|
|
210
77
|
@provided_values[key] = value
|
|
211
78
|
end
|
|
212
79
|
|
|
213
|
-
def_delegators :@query, :trace
|
|
80
|
+
def_delegators :@query, :trace
|
|
81
|
+
|
|
82
|
+
def types
|
|
83
|
+
@types ||= @query.types
|
|
84
|
+
end
|
|
214
85
|
|
|
215
|
-
|
|
86
|
+
attr_writer :types
|
|
87
|
+
|
|
88
|
+
RUNTIME_METADATA_KEYS = Set.new([:current_object, :current_arguments, :current_field, :current_path]).freeze
|
|
216
89
|
# @!method []=(key, value)
|
|
217
90
|
# Reassign `key` to the hash passed to {Schema#execute} as `context:`
|
|
218
91
|
|
|
@@ -226,7 +99,7 @@ module GraphQL
|
|
|
226
99
|
if key == :current_path
|
|
227
100
|
current_path
|
|
228
101
|
else
|
|
229
|
-
(current_runtime_state =
|
|
102
|
+
(current_runtime_state = Fiber[:__graphql_runtime_info]) &&
|
|
230
103
|
(query_runtime_state = current_runtime_state[@query]) &&
|
|
231
104
|
(query_runtime_state.public_send(key))
|
|
232
105
|
end
|
|
@@ -236,8 +109,37 @@ module GraphQL
|
|
|
236
109
|
end
|
|
237
110
|
end
|
|
238
111
|
|
|
112
|
+
# Return this value to tell the runtime
|
|
113
|
+
# to exclude this field from the response altogether
|
|
114
|
+
def skip
|
|
115
|
+
GraphQL::Execution::SKIP
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Add error at query-level.
|
|
119
|
+
# @param error [GraphQL::ExecutionError] an execution error
|
|
120
|
+
# @return [void]
|
|
121
|
+
def add_error(error)
|
|
122
|
+
if !error.is_a?(GraphQL::RuntimeError)
|
|
123
|
+
raise TypeError, "expected error to be a GraphQL::RuntimeError, but was #{error.class}"
|
|
124
|
+
end
|
|
125
|
+
errors << error
|
|
126
|
+
nil
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# @example Print the GraphQL backtrace during field resolution
|
|
130
|
+
# puts ctx.backtrace
|
|
131
|
+
#
|
|
132
|
+
# @return [GraphQL::Backtrace] The backtrace for this point in query execution
|
|
133
|
+
def backtrace
|
|
134
|
+
GraphQL::Backtrace.new(self)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def execution_errors
|
|
138
|
+
@execution_errors ||= ExecutionErrors.new(self)
|
|
139
|
+
end
|
|
140
|
+
|
|
239
141
|
def current_path
|
|
240
|
-
current_runtime_state =
|
|
142
|
+
current_runtime_state = Fiber[:__graphql_runtime_info]
|
|
241
143
|
query_runtime_state = current_runtime_state && current_runtime_state[@query]
|
|
242
144
|
|
|
243
145
|
path = query_runtime_state &&
|
|
@@ -262,7 +164,7 @@ module GraphQL
|
|
|
262
164
|
|
|
263
165
|
def fetch(key, default = UNSPECIFIED_FETCH_DEFAULT)
|
|
264
166
|
if RUNTIME_METADATA_KEYS.include?(key)
|
|
265
|
-
(runtime =
|
|
167
|
+
(runtime = Fiber[:__graphql_runtime_info]) &&
|
|
266
168
|
(query_runtime_state = runtime[@query]) &&
|
|
267
169
|
(query_runtime_state.public_send(key))
|
|
268
170
|
elsif @scoped_context.key?(key)
|
|
@@ -280,7 +182,7 @@ module GraphQL
|
|
|
280
182
|
|
|
281
183
|
def dig(key, *other_keys)
|
|
282
184
|
if RUNTIME_METADATA_KEYS.include?(key)
|
|
283
|
-
(current_runtime_state =
|
|
185
|
+
(current_runtime_state = Fiber[:__graphql_runtime_info]) &&
|
|
284
186
|
(query_runtime_state = current_runtime_state[@query]) &&
|
|
285
187
|
(obj = query_runtime_state.public_send(key)) &&
|
|
286
188
|
if other_keys.empty?
|
|
@@ -333,8 +235,12 @@ module GraphQL
|
|
|
333
235
|
@storage.key?(ns)
|
|
334
236
|
end
|
|
335
237
|
|
|
238
|
+
def logger
|
|
239
|
+
@query && @query.logger
|
|
240
|
+
end
|
|
241
|
+
|
|
336
242
|
def inspect
|
|
337
|
-
"
|
|
243
|
+
"#<#{self.class} ...>"
|
|
338
244
|
end
|
|
339
245
|
|
|
340
246
|
def scoped_merge!(hash)
|
|
@@ -345,6 +251,38 @@ module GraphQL
|
|
|
345
251
|
scoped_merge!(key => value)
|
|
346
252
|
nil
|
|
347
253
|
end
|
|
254
|
+
|
|
255
|
+
# Use this when you need to do a scoped set _inside_ a lazy-loaded (or batch-loaded)
|
|
256
|
+
# block of code.
|
|
257
|
+
#
|
|
258
|
+
# @example using scoped context inside a promise
|
|
259
|
+
# scoped_ctx = context.scoped
|
|
260
|
+
# SomeBatchLoader.load(...).then do |thing|
|
|
261
|
+
# # use a scoped_ctx which was created _before_ dataloading:
|
|
262
|
+
# scoped_ctx.set!(:thing, thing)
|
|
263
|
+
# end
|
|
264
|
+
# @return [Context::Scoped]
|
|
265
|
+
def scoped
|
|
266
|
+
Scoped.new(@scoped_context, current_path)
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
class Scoped
|
|
270
|
+
def initialize(scoped_context, path)
|
|
271
|
+
@path = path
|
|
272
|
+
@scoped_context = scoped_context
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def merge!(hash)
|
|
276
|
+
@scoped_context.merge!(hash, at: @path)
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
def set!(key, value)
|
|
280
|
+
@scoped_context.merge!({ key => value }, at: @path)
|
|
281
|
+
nil
|
|
282
|
+
end
|
|
283
|
+
end
|
|
348
284
|
end
|
|
349
285
|
end
|
|
350
286
|
end
|
|
287
|
+
|
|
288
|
+
require "graphql/query/context/scoped_context"
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
require "graphql/query/context"
|
|
2
3
|
module GraphQL
|
|
3
4
|
class Query
|
|
4
5
|
# This object can be `ctx` in places where there is no query
|
|
5
|
-
class NullContext
|
|
6
|
+
class NullContext < Context
|
|
7
|
+
def self.instance
|
|
8
|
+
@instance ||= self.new
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.instance=(new_inst)
|
|
12
|
+
@instance = new_inst
|
|
13
|
+
end
|
|
14
|
+
|
|
6
15
|
class NullQuery
|
|
7
16
|
def after_lazy(value)
|
|
8
17
|
yield(value)
|
|
@@ -15,27 +24,15 @@ module GraphQL
|
|
|
15
24
|
extend Forwardable
|
|
16
25
|
|
|
17
26
|
attr_reader :schema, :query, :warden, :dataloader
|
|
18
|
-
def_delegators GraphQL::EmptyObjects::EMPTY_HASH, :[], :fetch, :dig, :key
|
|
27
|
+
def_delegators GraphQL::EmptyObjects::EMPTY_HASH, :[], :fetch, :dig, :key?, :to_h
|
|
19
28
|
|
|
20
|
-
def initialize
|
|
29
|
+
def initialize(schema: NullSchema)
|
|
21
30
|
@query = NullQuery.new
|
|
22
31
|
@dataloader = GraphQL::Dataloader::NullDataloader.new
|
|
23
|
-
@schema =
|
|
32
|
+
@schema = schema
|
|
24
33
|
@warden = Schema::Warden::NullWarden.new(context: self, schema: @schema)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def interpreter?
|
|
28
|
-
true
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
class << self
|
|
32
|
-
extend Forwardable
|
|
33
|
-
|
|
34
|
-
def instance
|
|
35
|
-
@instance ||= self.new
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def_delegators :instance, :query, :warden, :schema, :interpreter?, :dataloader, :[], :fetch, :dig, :key?
|
|
34
|
+
@types = @warden.visibility_profile
|
|
35
|
+
freeze
|
|
39
36
|
end
|
|
40
37
|
end
|
|
41
38
|
end
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module GraphQL
|
|
3
|
+
class Query
|
|
4
|
+
# This class is _like_ a {GraphQL::Query}, except it can run on an arbitrary path within a query string.
|
|
5
|
+
#
|
|
6
|
+
# It depends on a "parent" {Query}.
|
|
7
|
+
#
|
|
8
|
+
# During execution, it calls query-related tracing hooks but passes itself as `query:`.
|
|
9
|
+
#
|
|
10
|
+
# The {Partial} will use your {Schema.resolve_type} hook to find the right GraphQL type to use for
|
|
11
|
+
# `object` in some cases.
|
|
12
|
+
#
|
|
13
|
+
# @see Query#run_partials Run via {Query#run_partials}
|
|
14
|
+
class Partial
|
|
15
|
+
include Query::Runnable
|
|
16
|
+
|
|
17
|
+
# @param path [Array<String, Integer>] A path in `query.query_string` to start executing from
|
|
18
|
+
# @param object [Object] A starting object for execution
|
|
19
|
+
# @param query [GraphQL::Query] A full query instance that this partial is based on. Caches are shared.
|
|
20
|
+
# @param context [Hash] Extra context values to merge into `query.context`, if provided
|
|
21
|
+
# @param fragment_node [GraphQL::Language::Nodes::InlineFragment, GraphQL::Language::Nodes::FragmentDefinition]
|
|
22
|
+
def initialize(path: nil, object:, query:, context: nil, fragment_node: nil, type: nil)
|
|
23
|
+
@path = path
|
|
24
|
+
@object = object
|
|
25
|
+
@query = query
|
|
26
|
+
@schema = query.schema
|
|
27
|
+
context_vals = @query.context.to_h
|
|
28
|
+
if context
|
|
29
|
+
context_vals = context_vals.merge(context)
|
|
30
|
+
end
|
|
31
|
+
@context = GraphQL::Query::Context.new(query: self, schema: @query.schema, values: context_vals)
|
|
32
|
+
@multiplex = nil
|
|
33
|
+
@result_values = nil
|
|
34
|
+
@result = nil
|
|
35
|
+
|
|
36
|
+
if fragment_node
|
|
37
|
+
@ast_nodes = [fragment_node]
|
|
38
|
+
@root_type = type || raise(ArgumentError, "Pass `type:` when using `node:`")
|
|
39
|
+
# This is only used when `@leaf`
|
|
40
|
+
@field_definition = nil
|
|
41
|
+
elsif path.nil?
|
|
42
|
+
raise ArgumentError, "`path:` is required if `node:` is not given; add `path:`"
|
|
43
|
+
else
|
|
44
|
+
set_type_info_from_path
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
@leaf = @root_type.unwrap.kind.leaf?
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def leaf?
|
|
51
|
+
@leaf
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
attr_reader :context, :query, :ast_nodes, :root_type, :object, :field_definition, :path, :schema
|
|
55
|
+
|
|
56
|
+
attr_accessor :multiplex, :result_values
|
|
57
|
+
|
|
58
|
+
class Result < GraphQL::Query::Result
|
|
59
|
+
def path
|
|
60
|
+
@query.path
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# @return [GraphQL::Query::Partial]
|
|
64
|
+
def partial
|
|
65
|
+
@query
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def result
|
|
70
|
+
@result ||= Result.new(query: self, values: result_values)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def current_trace
|
|
74
|
+
@query.current_trace
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def types
|
|
78
|
+
@query.types
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def resolve_type(...)
|
|
82
|
+
@query.resolve_type(...)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def variables
|
|
86
|
+
@query.variables
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def fragments
|
|
90
|
+
@query.fragments
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def valid?
|
|
94
|
+
@query.valid?
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def analyzers
|
|
98
|
+
EmptyObjects::EMPTY_ARRAY
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def analysis_errors=(_ignored)
|
|
102
|
+
# pass
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def subscription?
|
|
106
|
+
@query.subscription?
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def selected_operation
|
|
110
|
+
ast_nodes.first
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def static_errors
|
|
114
|
+
@query.static_errors
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def selected_operation_name
|
|
118
|
+
@query.selected_operation_name
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
private
|
|
122
|
+
|
|
123
|
+
def set_type_info_from_path
|
|
124
|
+
selections = [@query.selected_operation]
|
|
125
|
+
type = @query.root_type
|
|
126
|
+
parent_type = nil
|
|
127
|
+
field_defn = nil
|
|
128
|
+
|
|
129
|
+
@path.each do |name_in_doc|
|
|
130
|
+
if name_in_doc.is_a?(Integer)
|
|
131
|
+
if type.list?
|
|
132
|
+
type = type.unwrap
|
|
133
|
+
next
|
|
134
|
+
else
|
|
135
|
+
raise ArgumentError, "Received path with index `#{name_in_doc}`, but type wasn't a list. Type: #{type.to_type_signature}, path: #{@path}"
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
next_selections = []
|
|
140
|
+
selections.each do |selection|
|
|
141
|
+
selections_to_check = []
|
|
142
|
+
selections_to_check.concat(selection.selections)
|
|
143
|
+
while (sel = selections_to_check.shift)
|
|
144
|
+
case sel
|
|
145
|
+
when GraphQL::Language::Nodes::InlineFragment
|
|
146
|
+
selections_to_check.concat(sel.selections)
|
|
147
|
+
when GraphQL::Language::Nodes::FragmentSpread
|
|
148
|
+
fragment = @query.fragments[sel.name]
|
|
149
|
+
selections_to_check.concat(fragment.selections)
|
|
150
|
+
when GraphQL::Language::Nodes::Field
|
|
151
|
+
if sel.alias == name_in_doc || sel.name == name_in_doc
|
|
152
|
+
next_selections << sel
|
|
153
|
+
end
|
|
154
|
+
else
|
|
155
|
+
raise "Unexpected selection in partial path: #{sel.class}, #{sel.inspect}"
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
if next_selections.empty?
|
|
161
|
+
raise ArgumentError, "Path `#{@path.inspect}` is not present in this query. `#{name_in_doc.inspect}` was not found. Try a different path or rewrite the query to include it."
|
|
162
|
+
end
|
|
163
|
+
field_name = next_selections.first.name
|
|
164
|
+
field_defn = @schema.get_field(type, field_name, @query.context) || raise("Invariant: no field called #{field_name} on #{type.graphql_name}")
|
|
165
|
+
parent_type = type
|
|
166
|
+
type = field_defn.type
|
|
167
|
+
if type.non_null?
|
|
168
|
+
type = type.of_type
|
|
169
|
+
end
|
|
170
|
+
selections = next_selections
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
@ast_nodes = selections
|
|
174
|
+
@root_type = type
|
|
175
|
+
@field_definition = field_defn
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|