graphql 1.10.1 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of graphql might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/generators/graphql/core.rb +18 -2
- data/lib/generators/graphql/install_generator.rb +36 -6
- data/lib/generators/graphql/loader_generator.rb +1 -0
- data/lib/generators/graphql/mutation_generator.rb +2 -1
- data/lib/generators/graphql/object_generator.rb +54 -9
- data/lib/generators/graphql/relay.rb +63 -0
- data/lib/generators/graphql/relay_generator.rb +21 -0
- data/lib/generators/graphql/templates/base_argument.erb +2 -0
- data/lib/generators/graphql/templates/base_connection.erb +8 -0
- data/lib/generators/graphql/templates/base_edge.erb +8 -0
- data/lib/generators/graphql/templates/base_enum.erb +2 -0
- data/lib/generators/graphql/templates/base_field.erb +2 -0
- data/lib/generators/graphql/templates/base_input_object.erb +2 -0
- data/lib/generators/graphql/templates/base_interface.erb +2 -0
- data/lib/generators/graphql/templates/base_mutation.erb +2 -0
- data/lib/generators/graphql/templates/base_object.erb +2 -0
- data/lib/generators/graphql/templates/base_scalar.erb +2 -0
- data/lib/generators/graphql/templates/base_union.erb +2 -0
- data/lib/generators/graphql/templates/enum.erb +2 -0
- data/lib/generators/graphql/templates/graphql_controller.erb +16 -12
- data/lib/generators/graphql/templates/interface.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/mutation_type.erb +2 -0
- data/lib/generators/graphql/templates/node_type.erb +9 -0
- data/lib/generators/graphql/templates/object.erb +3 -1
- data/lib/generators/graphql/templates/query_type.erb +3 -3
- data/lib/generators/graphql/templates/scalar.erb +2 -0
- data/lib/generators/graphql/templates/schema.erb +21 -33
- data/lib/generators/graphql/templates/union.erb +3 -1
- data/lib/generators/graphql/type_generator.rb +1 -1
- data/lib/graphql/analysis/analyze_query.rb +7 -0
- data/lib/graphql/analysis/ast/field_usage.rb +24 -1
- data/lib/graphql/analysis/ast/query_complexity.rb +126 -109
- data/lib/graphql/analysis/ast/visitor.rb +13 -5
- data/lib/graphql/analysis/ast.rb +11 -2
- data/lib/graphql/argument.rb +3 -3
- data/lib/graphql/backtrace/inspect_result.rb +0 -1
- data/lib/graphql/backtrace/legacy_tracer.rb +56 -0
- data/lib/graphql/backtrace/table.rb +34 -3
- data/lib/graphql/backtrace/traced_error.rb +0 -1
- data/lib/graphql/backtrace/tracer.rb +40 -9
- data/lib/graphql/backtrace.rb +28 -19
- data/lib/graphql/backwards_compatibility.rb +2 -1
- data/lib/graphql/base_type.rb +1 -1
- data/lib/graphql/compatibility/execution_specification/specification_schema.rb +2 -2
- data/lib/graphql/compatibility/execution_specification.rb +1 -0
- data/lib/graphql/compatibility/lazy_execution_specification.rb +2 -0
- data/lib/graphql/compatibility/query_parser_specification.rb +2 -0
- data/lib/graphql/compatibility/schema_parser_specification.rb +2 -0
- data/lib/graphql/dataloader/null_dataloader.rb +22 -0
- data/lib/graphql/dataloader/request.rb +19 -0
- data/lib/graphql/dataloader/request_all.rb +19 -0
- data/lib/graphql/dataloader/source.rb +155 -0
- data/lib/graphql/dataloader.rb +308 -0
- data/lib/graphql/define/assign_global_id_field.rb +2 -2
- data/lib/graphql/define/defined_object_proxy.rb +1 -1
- data/lib/graphql/define/instance_definable.rb +34 -4
- data/lib/graphql/define/type_definer.rb +5 -5
- data/lib/graphql/deprecated_dsl.rb +18 -5
- data/lib/graphql/deprecation.rb +9 -0
- data/lib/graphql/directive.rb +4 -4
- data/lib/graphql/enum_type.rb +7 -1
- data/lib/graphql/execution/errors.rb +110 -7
- data/lib/graphql/execution/execute.rb +8 -1
- data/lib/graphql/execution/instrumentation.rb +1 -1
- data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
- data/lib/graphql/execution/interpreter/arguments.rb +88 -0
- data/lib/graphql/execution/interpreter/arguments_cache.rb +103 -0
- data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
- data/lib/graphql/execution/interpreter/resolve.rb +37 -25
- data/lib/graphql/execution/interpreter/runtime.rb +685 -421
- data/lib/graphql/execution/interpreter.rb +42 -13
- data/lib/graphql/execution/lazy.rb +5 -1
- data/lib/graphql/execution/lookahead.rb +25 -110
- data/lib/graphql/execution/multiplex.rb +37 -25
- data/lib/graphql/field.rb +5 -1
- data/lib/graphql/function.rb +4 -0
- data/lib/graphql/input_object_type.rb +6 -0
- data/lib/graphql/integer_decoding_error.rb +17 -0
- data/lib/graphql/integer_encoding_error.rb +18 -2
- data/lib/graphql/interface_type.rb +7 -0
- data/lib/graphql/internal_representation/document.rb +2 -2
- data/lib/graphql/internal_representation/rewrite.rb +1 -1
- data/lib/graphql/internal_representation/scope.rb +2 -2
- data/lib/graphql/internal_representation/visit.rb +2 -2
- data/lib/graphql/introspection/directive_type.rb +8 -4
- data/lib/graphql/introspection/entry_points.rb +2 -2
- data/lib/graphql/introspection/enum_value_type.rb +2 -2
- data/lib/graphql/introspection/field_type.rb +9 -5
- data/lib/graphql/introspection/input_value_type.rb +15 -3
- data/lib/graphql/introspection/introspection_query.rb +6 -92
- data/lib/graphql/introspection/schema_type.rb +4 -4
- data/lib/graphql/introspection/type_type.rb +16 -12
- data/lib/graphql/introspection.rb +96 -0
- data/lib/graphql/invalid_null_error.rb +18 -0
- data/lib/graphql/language/block_string.rb +20 -5
- data/lib/graphql/language/cache.rb +37 -0
- data/lib/graphql/language/document_from_schema_definition.rb +73 -25
- data/lib/graphql/language/lexer.rb +4 -3
- data/lib/graphql/language/lexer.rl +3 -3
- data/lib/graphql/language/nodes.rb +51 -89
- data/lib/graphql/language/parser.rb +552 -530
- data/lib/graphql/language/parser.y +114 -99
- data/lib/graphql/language/printer.rb +7 -2
- data/lib/graphql/language/sanitized_printer.rb +222 -0
- data/lib/graphql/language/token.rb +0 -4
- data/lib/graphql/language/visitor.rb +2 -2
- data/lib/graphql/language.rb +2 -0
- data/lib/graphql/name_validator.rb +2 -7
- data/lib/graphql/object_type.rb +44 -35
- data/lib/graphql/pagination/active_record_relation_connection.rb +14 -1
- data/lib/graphql/pagination/array_connection.rb +2 -2
- data/lib/graphql/pagination/connection.rb +75 -20
- data/lib/graphql/pagination/connections.rb +83 -31
- data/lib/graphql/pagination/relation_connection.rb +34 -14
- data/lib/graphql/parse_error.rb +0 -1
- data/lib/graphql/query/arguments.rb +4 -3
- data/lib/graphql/query/arguments_cache.rb +1 -2
- data/lib/graphql/query/context.rb +42 -7
- data/lib/graphql/query/executor.rb +0 -1
- data/lib/graphql/query/fingerprint.rb +26 -0
- data/lib/graphql/query/input_validation_result.rb +23 -6
- data/lib/graphql/query/literal_input.rb +1 -1
- data/lib/graphql/query/null_context.rb +24 -8
- data/lib/graphql/query/serial_execution/field_resolution.rb +1 -1
- data/lib/graphql/query/serial_execution.rb +1 -0
- data/lib/graphql/query/validation_pipeline.rb +5 -2
- data/lib/graphql/query/variable_validation_error.rb +1 -1
- data/lib/graphql/query/variables.rb +14 -4
- data/lib/graphql/query.rb +68 -13
- data/lib/graphql/railtie.rb +9 -1
- data/lib/graphql/rake_task.rb +12 -9
- data/lib/graphql/relay/array_connection.rb +10 -12
- data/lib/graphql/relay/base_connection.rb +26 -13
- data/lib/graphql/relay/connection_instrumentation.rb +4 -4
- data/lib/graphql/relay/connection_type.rb +1 -1
- data/lib/graphql/relay/edges_instrumentation.rb +0 -1
- data/lib/graphql/relay/mutation.rb +1 -0
- data/lib/graphql/relay/node.rb +3 -0
- data/lib/graphql/relay/range_add.rb +23 -9
- data/lib/graphql/relay/relation_connection.rb +8 -10
- data/lib/graphql/relay/type_extensions.rb +2 -0
- data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
- data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
- data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
- data/lib/graphql/rubocop.rb +4 -0
- data/lib/graphql/scalar_type.rb +16 -1
- data/lib/graphql/schema/addition.rb +247 -0
- data/lib/graphql/schema/argument.rb +210 -12
- data/lib/graphql/schema/base_64_encoder.rb +2 -0
- data/lib/graphql/schema/build_from_definition/resolve_map.rb +3 -1
- data/lib/graphql/schema/build_from_definition.rb +213 -86
- data/lib/graphql/schema/default_type_error.rb +2 -0
- data/lib/graphql/schema/directive/deprecated.rb +1 -1
- data/lib/graphql/schema/directive/feature.rb +1 -1
- data/lib/graphql/schema/directive/flagged.rb +57 -0
- data/lib/graphql/schema/directive/include.rb +1 -1
- data/lib/graphql/schema/directive/skip.rb +1 -1
- data/lib/graphql/schema/directive/transform.rb +14 -2
- data/lib/graphql/schema/directive.rb +78 -2
- data/lib/graphql/schema/enum.rb +80 -9
- data/lib/graphql/schema/enum_value.rb +17 -6
- data/lib/graphql/schema/field/connection_extension.rb +46 -30
- data/lib/graphql/schema/field/scope_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +285 -133
- data/lib/graphql/schema/find_inherited_value.rb +4 -1
- data/lib/graphql/schema/finder.rb +5 -5
- data/lib/graphql/schema/input_object.rb +97 -89
- data/lib/graphql/schema/interface.rb +24 -19
- data/lib/graphql/schema/late_bound_type.rb +2 -2
- data/lib/graphql/schema/list.rb +7 -1
- data/lib/graphql/schema/loader.rb +137 -103
- data/lib/graphql/schema/member/accepts_definition.rb +8 -1
- data/lib/graphql/schema/member/base_dsl_methods.rb +15 -19
- data/lib/graphql/schema/member/build_type.rb +14 -7
- data/lib/graphql/schema/member/has_arguments.rb +205 -12
- data/lib/graphql/schema/member/has_ast_node.rb +4 -1
- data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
- data/lib/graphql/schema/member/has_directives.rb +98 -0
- data/lib/graphql/schema/member/has_fields.rb +95 -30
- data/lib/graphql/schema/member/has_interfaces.rb +90 -0
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
- data/lib/graphql/schema/member/has_validators.rb +31 -0
- data/lib/graphql/schema/member/instrumentation.rb +0 -1
- data/lib/graphql/schema/member/type_system_helpers.rb +3 -3
- data/lib/graphql/schema/member.rb +6 -0
- data/lib/graphql/schema/middleware_chain.rb +1 -1
- data/lib/graphql/schema/mutation.rb +4 -0
- data/lib/graphql/schema/non_null.rb +5 -0
- data/lib/graphql/schema/object.rb +47 -46
- data/lib/graphql/schema/possible_types.rb +9 -4
- data/lib/graphql/schema/printer.rb +16 -34
- data/lib/graphql/schema/relay_classic_mutation.rb +32 -4
- data/lib/graphql/schema/resolver/has_payload_type.rb +34 -4
- data/lib/graphql/schema/resolver.rb +123 -63
- data/lib/graphql/schema/scalar.rb +11 -1
- data/lib/graphql/schema/subscription.rb +57 -21
- data/lib/graphql/schema/timeout.rb +29 -15
- data/lib/graphql/schema/timeout_middleware.rb +3 -1
- data/lib/graphql/schema/type_expression.rb +1 -1
- data/lib/graphql/schema/type_membership.rb +18 -4
- data/lib/graphql/schema/union.rb +41 -1
- data/lib/graphql/schema/unique_within_type.rb +1 -2
- data/lib/graphql/schema/validation.rb +12 -2
- data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
- data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
- data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
- data/lib/graphql/schema/validator/format_validator.rb +48 -0
- data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
- data/lib/graphql/schema/validator/length_validator.rb +59 -0
- data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
- data/lib/graphql/schema/validator/required_validator.rb +68 -0
- data/lib/graphql/schema/validator.rb +174 -0
- data/lib/graphql/schema/warden.rb +153 -28
- data/lib/graphql/schema.rb +364 -330
- data/lib/graphql/static_validation/all_rules.rb +1 -0
- data/lib/graphql/static_validation/base_visitor.rb +8 -5
- data/lib/graphql/static_validation/definition_dependencies.rb +0 -1
- data/lib/graphql/static_validation/error.rb +3 -1
- data/lib/graphql/static_validation/literal_validator.rb +51 -26
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +44 -87
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +22 -6
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +28 -22
- data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +79 -43
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
- data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
- data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +1 -1
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +6 -7
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +9 -10
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +8 -8
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +4 -2
- data/lib/graphql/static_validation/validation_context.rb +9 -3
- data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
- data/lib/graphql/static_validation/validator.rb +42 -8
- data/lib/graphql/static_validation.rb +1 -0
- data/lib/graphql/string_encoding_error.rb +13 -3
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +118 -19
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +21 -0
- data/lib/graphql/subscriptions/event.rb +81 -30
- data/lib/graphql/subscriptions/instrumentation.rb +0 -1
- data/lib/graphql/subscriptions/serialize.rb +33 -6
- data/lib/graphql/subscriptions/subscription_root.rb +15 -4
- data/lib/graphql/subscriptions.rb +88 -45
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +2 -1
- data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
- data/lib/graphql/tracing/appsignal_tracing.rb +15 -0
- data/lib/graphql/tracing/new_relic_tracing.rb +1 -12
- data/lib/graphql/tracing/platform_tracing.rb +43 -17
- data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
- data/lib/graphql/tracing/scout_tracing.rb +11 -0
- data/lib/graphql/tracing/skylight_tracing.rb +1 -1
- data/lib/graphql/tracing/statsd_tracing.rb +42 -0
- data/lib/graphql/tracing.rb +9 -33
- data/lib/graphql/types/big_int.rb +5 -1
- data/lib/graphql/types/int.rb +10 -3
- data/lib/graphql/types/iso_8601_date.rb +3 -3
- data/lib/graphql/types/iso_8601_date_time.rb +25 -10
- data/lib/graphql/types/relay/base_connection.rb +6 -90
- data/lib/graphql/types/relay/base_edge.rb +2 -34
- data/lib/graphql/types/relay/connection_behaviors.rb +156 -0
- data/lib/graphql/types/relay/default_relay.rb +27 -0
- data/lib/graphql/types/relay/edge_behaviors.rb +53 -0
- data/lib/graphql/types/relay/has_node_field.rb +41 -0
- data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
- data/lib/graphql/types/relay/node.rb +2 -4
- data/lib/graphql/types/relay/node_behaviors.rb +15 -0
- data/lib/graphql/types/relay/node_field.rb +2 -20
- data/lib/graphql/types/relay/nodes_field.rb +2 -20
- data/lib/graphql/types/relay/page_info.rb +2 -14
- data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
- data/lib/graphql/types/relay.rb +11 -3
- data/lib/graphql/types/string.rb +8 -2
- data/lib/graphql/unauthorized_error.rb +2 -2
- data/lib/graphql/union_type.rb +2 -0
- data/lib/graphql/upgrader/member.rb +1 -0
- data/lib/graphql/upgrader/schema.rb +1 -0
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +65 -31
- data/readme.md +3 -6
- metadata +77 -112
- data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
- data/lib/graphql/literal_validation_error.rb +0 -6
- data/lib/graphql/types/relay/base_field.rb +0 -22
- data/lib/graphql/types/relay/base_interface.rb +0 -29
- data/lib/graphql/types/relay/base_object.rb +0 -26
@@ -6,7 +6,7 @@ module GraphQL
|
|
6
6
|
class Execute
|
7
7
|
|
8
8
|
# @api private
|
9
|
-
class Skip; end
|
9
|
+
class Skip < GraphQL::Error; end
|
10
10
|
|
11
11
|
# Just a singleton for implementing {Query::Context#skip}
|
12
12
|
# @api private
|
@@ -18,7 +18,14 @@ module GraphQL
|
|
18
18
|
# @api private
|
19
19
|
PROPAGATE_NULL = PropagateNull.new
|
20
20
|
|
21
|
+
def self.use(schema_class)
|
22
|
+
schema_class.query_execution_strategy(self)
|
23
|
+
schema_class.mutation_execution_strategy(self)
|
24
|
+
schema_class.subscription_execution_strategy(self)
|
25
|
+
end
|
26
|
+
|
21
27
|
def execute(ast_operation, root_type, query)
|
28
|
+
GraphQL::Deprecation.warn "#{self.class} will be removed in GraphQL-Ruby 2.0, please upgrade to the Interpreter: https://graphql-ruby.org/queries/interpreter.html"
|
22
29
|
result = resolve_root_selection(query)
|
23
30
|
lazy_resolve_root_selection(result, **{query: query})
|
24
31
|
GraphQL::Execution::Flatten.call(query.context)
|
@@ -77,7 +77,7 @@ module GraphQL
|
|
77
77
|
end
|
78
78
|
|
79
79
|
def call_after_hooks(instrumenters, object, after_hook_name, ex)
|
80
|
-
instrumenters.
|
80
|
+
instrumenters.reverse_each do |instrumenter|
|
81
81
|
begin
|
82
82
|
instrumenter.public_send(after_hook_name, object)
|
83
83
|
rescue => e
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Execution
|
5
|
+
class Interpreter
|
6
|
+
# A container for metadata regarding arguments present in a GraphQL query.
|
7
|
+
# @see Interpreter::Arguments#argument_values for a hash of these objects.
|
8
|
+
class ArgumentValue
|
9
|
+
def initialize(definition:, value:, default_used:)
|
10
|
+
@definition = definition
|
11
|
+
@value = value
|
12
|
+
@default_used = default_used
|
13
|
+
end
|
14
|
+
|
15
|
+
# @return [Object] The Ruby-ready value for this Argument
|
16
|
+
attr_reader :value
|
17
|
+
|
18
|
+
# @return [GraphQL::Schema::Argument] The definition instance for this argument
|
19
|
+
attr_reader :definition
|
20
|
+
|
21
|
+
# @return [Boolean] `true` if the schema-defined `default_value:` was applied in this case. (No client-provided value was present.)
|
22
|
+
def default_used?
|
23
|
+
@default_used
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Execution
|
5
|
+
class Interpreter
|
6
|
+
# A wrapper for argument hashes in GraphQL queries.
|
7
|
+
#
|
8
|
+
# This object is immutable so that the runtime code can be sure that
|
9
|
+
# modifications don't leak from one use to another
|
10
|
+
#
|
11
|
+
# @see GraphQL::Query#arguments_for to get access to these objects.
|
12
|
+
class Arguments
|
13
|
+
extend Forwardable
|
14
|
+
include GraphQL::Dig
|
15
|
+
|
16
|
+
# The Ruby-style arguments hash, ready for a resolver.
|
17
|
+
# This hash is the one used at runtime.
|
18
|
+
#
|
19
|
+
# @return [Hash<Symbol, Object>]
|
20
|
+
attr_reader :keyword_arguments
|
21
|
+
|
22
|
+
# @param argument_values [nil, Hash{Symbol => ArgumentValue}]
|
23
|
+
# @param keyword_arguments [nil, Hash{Symbol => Object}]
|
24
|
+
def initialize(keyword_arguments: nil, argument_values:)
|
25
|
+
@empty = argument_values.nil? || argument_values.empty?
|
26
|
+
# This is only present when `extras` have been merged in:
|
27
|
+
if keyword_arguments
|
28
|
+
# This is a little crazy. We expect the `:argument_details` extra to _include extras_,
|
29
|
+
# but the object isn't created until _after_ extras are put together.
|
30
|
+
# So, we have to use a special flag here to say, "at the last minute, add yourself to the keyword args."
|
31
|
+
#
|
32
|
+
# Otherwise:
|
33
|
+
# - We can't access the final Arguments instance _while_ we're preparing extras
|
34
|
+
# - After we _can_ access it, it's frozen, so we can't add anything.
|
35
|
+
#
|
36
|
+
# So, this flag gives us a chance to sneak it in before freezing, _and_ while we have access
|
37
|
+
# to the new Arguments instance itself.
|
38
|
+
if keyword_arguments[:argument_details] == :__arguments_add_self
|
39
|
+
keyword_arguments[:argument_details] = self
|
40
|
+
end
|
41
|
+
@keyword_arguments = keyword_arguments.freeze
|
42
|
+
elsif !@empty
|
43
|
+
@keyword_arguments = {}
|
44
|
+
argument_values.each do |name, arg_val|
|
45
|
+
@keyword_arguments[name] = arg_val.value
|
46
|
+
end
|
47
|
+
@keyword_arguments.freeze
|
48
|
+
else
|
49
|
+
@keyword_arguments = NO_ARGS
|
50
|
+
end
|
51
|
+
@argument_values = argument_values ? argument_values.freeze : NO_ARGS
|
52
|
+
freeze
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [Hash{Symbol => ArgumentValue}]
|
56
|
+
attr_reader :argument_values
|
57
|
+
|
58
|
+
def empty?
|
59
|
+
@empty
|
60
|
+
end
|
61
|
+
|
62
|
+
def_delegators :keyword_arguments, :key?, :[], :fetch, :keys, :each, :values, :size, :to_h
|
63
|
+
def_delegators :argument_values, :each_value
|
64
|
+
|
65
|
+
def inspect
|
66
|
+
"#<#{self.class} @keyword_arguments=#{keyword_arguments.inspect}>"
|
67
|
+
end
|
68
|
+
|
69
|
+
# Create a new arguments instance which includes these extras.
|
70
|
+
#
|
71
|
+
# This is called by the runtime to implement field `extras: [...]`
|
72
|
+
#
|
73
|
+
# @param extra_args [Hash<Symbol => Object>]
|
74
|
+
# @return [Interpreter::Arguments]
|
75
|
+
# @api private
|
76
|
+
def merge_extras(extra_args)
|
77
|
+
self.class.new(
|
78
|
+
argument_values: argument_values,
|
79
|
+
keyword_arguments: keyword_arguments.merge(extra_args)
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
83
|
+
NO_ARGS = {}.freeze
|
84
|
+
EMPTY = self.new(argument_values: nil, keyword_arguments: NO_ARGS).freeze
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Execution
|
5
|
+
class Interpreter
|
6
|
+
class ArgumentsCache
|
7
|
+
def initialize(query)
|
8
|
+
@query = query
|
9
|
+
@dataloader = query.context.dataloader
|
10
|
+
@storage = Hash.new do |h, ast_node|
|
11
|
+
h[ast_node] = Hash.new do |h2, arg_owner|
|
12
|
+
h2[arg_owner] = Hash.new do |h3, parent_object|
|
13
|
+
dataload_for(ast_node, arg_owner, parent_object) do |kwarg_arguments|
|
14
|
+
h3[parent_object] = @query.schema.after_lazy(kwarg_arguments) do |resolved_args|
|
15
|
+
h3[parent_object] = resolved_args
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
if !h3.key?(parent_object)
|
20
|
+
# TODO should i bother putting anything here?
|
21
|
+
h3[parent_object] = NO_ARGUMENTS
|
22
|
+
else
|
23
|
+
h3[parent_object]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def fetch(ast_node, argument_owner, parent_object)
|
31
|
+
# If any jobs were enqueued, run them now,
|
32
|
+
# since this might have been called outside of execution.
|
33
|
+
# (The jobs are responsible for updating `result` in-place.)
|
34
|
+
@dataloader.run_isolated do
|
35
|
+
@storage[ast_node][argument_owner][parent_object]
|
36
|
+
end
|
37
|
+
# Ack, the _hash_ is updated, but the key is eventually
|
38
|
+
# overridden with an immutable arguments instance.
|
39
|
+
# The first call queues up the job,
|
40
|
+
# then this call fetches the result.
|
41
|
+
# TODO this should be better, find a solution
|
42
|
+
# that works with merging the runtime.rb code
|
43
|
+
@storage[ast_node][argument_owner][parent_object]
|
44
|
+
end
|
45
|
+
|
46
|
+
# @yield [Interpreter::Arguments, Lazy<Interpreter::Arguments>] The finally-loaded arguments
|
47
|
+
def dataload_for(ast_node, argument_owner, parent_object, &block)
|
48
|
+
# First, normalize all AST or Ruby values to a plain Ruby hash
|
49
|
+
args_hash = self.class.prepare_args_hash(@query, ast_node)
|
50
|
+
argument_owner.coerce_arguments(parent_object, args_hash, @query.context, &block)
|
51
|
+
nil
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
NO_ARGUMENTS = {}.freeze
|
57
|
+
|
58
|
+
NO_VALUE_GIVEN = Object.new
|
59
|
+
|
60
|
+
def self.prepare_args_hash(query, ast_arg_or_hash_or_value)
|
61
|
+
case ast_arg_or_hash_or_value
|
62
|
+
when Hash
|
63
|
+
if ast_arg_or_hash_or_value.empty?
|
64
|
+
return NO_ARGUMENTS
|
65
|
+
end
|
66
|
+
args_hash = {}
|
67
|
+
ast_arg_or_hash_or_value.each do |k, v|
|
68
|
+
args_hash[k] = prepare_args_hash(query, v)
|
69
|
+
end
|
70
|
+
args_hash
|
71
|
+
when Array
|
72
|
+
ast_arg_or_hash_or_value.map { |v| prepare_args_hash(query, v) }
|
73
|
+
when GraphQL::Language::Nodes::Field, GraphQL::Language::Nodes::InputObject, GraphQL::Language::Nodes::Directive
|
74
|
+
if ast_arg_or_hash_or_value.arguments.empty? # rubocop:disable Development/ContextIsPassedCop -- AST-related
|
75
|
+
return NO_ARGUMENTS
|
76
|
+
end
|
77
|
+
args_hash = {}
|
78
|
+
ast_arg_or_hash_or_value.arguments.each do |arg| # rubocop:disable Development/ContextIsPassedCop -- AST-related
|
79
|
+
v = prepare_args_hash(query, arg.value)
|
80
|
+
if v != NO_VALUE_GIVEN
|
81
|
+
args_hash[arg.name] = v
|
82
|
+
end
|
83
|
+
end
|
84
|
+
args_hash
|
85
|
+
when GraphQL::Language::Nodes::VariableIdentifier
|
86
|
+
if query.variables.key?(ast_arg_or_hash_or_value.name)
|
87
|
+
variable_value = query.variables[ast_arg_or_hash_or_value.name]
|
88
|
+
prepare_args_hash(query, variable_value)
|
89
|
+
else
|
90
|
+
NO_VALUE_GIVEN
|
91
|
+
end
|
92
|
+
when GraphQL::Language::Nodes::Enum
|
93
|
+
ast_arg_or_hash_or_value.name
|
94
|
+
when GraphQL::Language::Nodes::NullValue
|
95
|
+
nil
|
96
|
+
else
|
97
|
+
ast_arg_or_hash_or_value
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Execution
|
5
|
+
class Interpreter
|
6
|
+
# Wrapper for raw values
|
7
|
+
class RawValue
|
8
|
+
def initialize(obj = nil)
|
9
|
+
@object = obj
|
10
|
+
end
|
11
|
+
|
12
|
+
def resolve
|
13
|
+
@object
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -6,10 +6,9 @@ module GraphQL
|
|
6
6
|
module Resolve
|
7
7
|
# Continue field results in `results` until there's nothing else to continue.
|
8
8
|
# @return [void]
|
9
|
-
def self.resolve_all(results)
|
10
|
-
|
11
|
-
|
12
|
-
end
|
9
|
+
def self.resolve_all(results, dataloader)
|
10
|
+
dataloader.append_job { resolve(results, dataloader) }
|
11
|
+
nil
|
13
12
|
end
|
14
13
|
|
15
14
|
# After getting `results` back from an interpreter evaluation,
|
@@ -24,33 +23,46 @@ module GraphQL
|
|
24
23
|
# return {Lazy} instances if there's more work to be done,
|
25
24
|
# or return {Hash}/{Array} if the query should be continued.
|
26
25
|
#
|
27
|
-
# @
|
28
|
-
|
29
|
-
|
26
|
+
# @return [void]
|
27
|
+
def self.resolve(results, dataloader)
|
28
|
+
# There might be pending jobs here that _will_ write lazies
|
29
|
+
# into the result hash. We should run them out, so we
|
30
|
+
# can be sure that all lazies will be present in the result hashes.
|
31
|
+
# A better implementation would somehow interleave (or unify)
|
32
|
+
# these approaches.
|
33
|
+
dataloader.run
|
30
34
|
next_results = []
|
31
|
-
|
32
|
-
# Work through the queue until it's empty
|
33
|
-
while results.size > 0
|
35
|
+
while results.any?
|
34
36
|
result_value = results.shift
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
# Since this field returned another lazy,
|
42
|
-
# add it to the same queue
|
43
|
-
results << result_value
|
44
|
-
elsif result_value.is_a?(Hash)
|
45
|
-
# This is part of the next level, add it
|
46
|
-
next_results.concat(result_value.values)
|
37
|
+
if result_value.is_a?(Runtime::GraphQLResultHash) || result_value.is_a?(Hash)
|
38
|
+
results.concat(result_value.values)
|
39
|
+
next
|
40
|
+
elsif result_value.is_a?(Runtime::GraphQLResultArray)
|
41
|
+
results.concat(result_value.values)
|
42
|
+
next
|
47
43
|
elsif result_value.is_a?(Array)
|
48
|
-
|
49
|
-
|
44
|
+
results.concat(result_value)
|
45
|
+
next
|
46
|
+
elsif result_value.is_a?(Lazy)
|
47
|
+
loaded_value = result_value.value
|
48
|
+
if loaded_value.is_a?(Lazy)
|
49
|
+
# Since this field returned another lazy,
|
50
|
+
# add it to the same queue
|
51
|
+
results << loaded_value
|
52
|
+
elsif loaded_value.is_a?(Runtime::GraphQLResultHash) || loaded_value.is_a?(Runtime::GraphQLResultArray) ||
|
53
|
+
loaded_value.is_a?(Hash) || loaded_value.is_a?(Array)
|
54
|
+
# Add these values in wholesale --
|
55
|
+
# they might be modified by later work in the dataloader.
|
56
|
+
next_results << loaded_value
|
57
|
+
end
|
50
58
|
end
|
51
59
|
end
|
52
60
|
|
53
|
-
next_results
|
61
|
+
if next_results.any?
|
62
|
+
dataloader.append_job { resolve(next_results, dataloader) }
|
63
|
+
end
|
64
|
+
|
65
|
+
nil
|
54
66
|
end
|
55
67
|
end
|
56
68
|
end
|