graphql 1.2.6 → 1.3.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.
- checksums.yaml +4 -4
- data/lib/graphql.rb +3 -1
- data/lib/graphql/analysis.rb +1 -0
- data/lib/graphql/analysis/analyze_query.rb +1 -0
- data/lib/graphql/analysis/field_usage.rb +1 -0
- data/lib/graphql/analysis/max_query_complexity.rb +1 -0
- data/lib/graphql/analysis/max_query_depth.rb +1 -0
- data/lib/graphql/analysis/query_complexity.rb +1 -0
- data/lib/graphql/analysis/query_depth.rb +1 -0
- data/lib/graphql/analysis/reducer_state.rb +1 -0
- data/lib/graphql/analysis_error.rb +1 -0
- data/lib/graphql/argument.rb +1 -0
- data/lib/graphql/base_type.rb +16 -7
- data/lib/graphql/boolean_type.rb +1 -0
- data/lib/graphql/compatibility.rb +2 -0
- data/lib/graphql/compatibility/execution_specification.rb +113 -192
- data/lib/graphql/compatibility/execution_specification/counter_schema.rb +53 -0
- data/lib/graphql/compatibility/execution_specification/specification_schema.rb +195 -0
- data/lib/graphql/compatibility/lazy_execution_specification.rb +186 -0
- data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +97 -0
- data/lib/graphql/compatibility/query_parser_specification.rb +1 -0
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +1 -0
- data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +1 -0
- data/lib/graphql/compatibility/schema_parser_specification.rb +1 -0
- data/lib/graphql/define.rb +1 -0
- data/lib/graphql/define/assign_argument.rb +1 -0
- data/lib/graphql/define/assign_connection.rb +1 -0
- data/lib/graphql/define/assign_enum_value.rb +1 -0
- data/lib/graphql/define/assign_global_id_field.rb +1 -0
- data/lib/graphql/define/assign_object_field.rb +1 -0
- data/lib/graphql/define/defined_object_proxy.rb +1 -0
- data/lib/graphql/define/instance_definable.rb +11 -12
- data/lib/graphql/define/non_null_with_bang.rb +1 -0
- data/lib/graphql/define/type_definer.rb +1 -0
- data/lib/graphql/directive.rb +1 -0
- data/lib/graphql/directive/deprecated_directive.rb +1 -0
- data/lib/graphql/directive/include_directive.rb +1 -0
- data/lib/graphql/directive/skip_directive.rb +1 -0
- data/lib/graphql/enum_type.rb +8 -1
- data/lib/graphql/execution.rb +5 -0
- data/lib/graphql/execution/directive_checks.rb +1 -0
- data/lib/graphql/execution/execute.rb +222 -0
- data/lib/graphql/execution/field_result.rb +52 -0
- data/lib/graphql/execution/lazy.rb +59 -0
- data/lib/graphql/execution/lazy/lazy_method_map.rb +38 -0
- data/lib/graphql/execution/lazy/resolve.rb +68 -0
- data/lib/graphql/execution/selection_result.rb +84 -0
- data/lib/graphql/execution/typecast.rb +4 -4
- data/lib/graphql/execution_error.rb +1 -0
- data/lib/graphql/field.rb +68 -18
- data/lib/graphql/field/resolve.rb +1 -0
- data/lib/graphql/float_type.rb +1 -0
- data/lib/graphql/id_type.rb +1 -0
- data/lib/graphql/input_object_type.rb +6 -0
- data/lib/graphql/int_type.rb +1 -0
- data/lib/graphql/interface_type.rb +6 -0
- data/lib/graphql/internal_representation.rb +2 -1
- data/lib/graphql/internal_representation/node.rb +2 -1
- data/lib/graphql/internal_representation/rewrite.rb +1 -0
- data/lib/graphql/internal_representation/selection.rb +85 -0
- data/lib/graphql/introspection.rb +1 -0
- data/lib/graphql/introspection/arguments_field.rb +1 -0
- data/lib/graphql/introspection/directive_location_enum.rb +1 -0
- data/lib/graphql/introspection/directive_type.rb +1 -0
- data/lib/graphql/introspection/enum_value_type.rb +1 -0
- data/lib/graphql/introspection/enum_values_field.rb +1 -0
- data/lib/graphql/introspection/field_type.rb +1 -0
- data/lib/graphql/introspection/fields_field.rb +1 -0
- data/lib/graphql/introspection/input_fields_field.rb +1 -0
- data/lib/graphql/introspection/input_value_type.rb +2 -1
- data/lib/graphql/introspection/interfaces_field.rb +1 -0
- data/lib/graphql/introspection/introspection_query.rb +1 -0
- data/lib/graphql/introspection/of_type_field.rb +1 -0
- data/lib/graphql/introspection/possible_types_field.rb +1 -0
- data/lib/graphql/introspection/schema_field.rb +1 -0
- data/lib/graphql/introspection/schema_type.rb +1 -0
- data/lib/graphql/introspection/type_by_name_field.rb +1 -0
- data/lib/graphql/introspection/type_kind_enum.rb +1 -0
- data/lib/graphql/introspection/type_type.rb +1 -0
- data/lib/graphql/introspection/typename_field.rb +1 -0
- data/lib/graphql/invalid_null_error.rb +17 -7
- data/lib/graphql/language.rb +10 -0
- data/lib/graphql/language/comments.rb +2 -1
- data/lib/graphql/language/definition_slice.rb +1 -0
- data/lib/graphql/language/generation.rb +25 -24
- data/lib/graphql/language/nodes.rb +1 -0
- data/lib/graphql/language/token.rb +1 -0
- data/lib/graphql/language/visitor.rb +1 -0
- data/lib/graphql/list_type.rb +1 -0
- data/lib/graphql/non_null_type.rb +2 -1
- data/lib/graphql/object_type.rb +12 -0
- data/lib/graphql/query.rb +40 -43
- data/lib/graphql/query/arguments.rb +1 -0
- data/lib/graphql/query/context.rb +31 -7
- data/lib/graphql/query/executor.rb +8 -1
- data/lib/graphql/query/input_validation_result.rb +1 -0
- data/lib/graphql/query/literal_input.rb +1 -0
- data/lib/graphql/query/serial_execution.rb +3 -4
- data/lib/graphql/query/serial_execution/field_resolution.rb +15 -10
- data/lib/graphql/query/serial_execution/operation_resolution.rb +3 -5
- data/lib/graphql/query/serial_execution/selection_resolution.rb +4 -5
- data/lib/graphql/query/serial_execution/value_resolution.rb +26 -11
- data/lib/graphql/query/variable_validation_error.rb +1 -0
- data/lib/graphql/query/variables.rb +1 -0
- data/lib/graphql/relay.rb +1 -0
- data/lib/graphql/relay/array_connection.rb +3 -2
- data/lib/graphql/relay/base_connection.rb +20 -8
- data/lib/graphql/relay/connection_field.rb +1 -0
- data/lib/graphql/relay/connection_resolve.rb +14 -1
- data/lib/graphql/relay/connection_type.rb +1 -0
- data/lib/graphql/relay/edge.rb +1 -0
- data/lib/graphql/relay/edge_type.rb +1 -0
- data/lib/graphql/relay/global_id_resolve.rb +1 -0
- data/lib/graphql/relay/mutation.rb +13 -0
- data/lib/graphql/relay/node.rb +1 -0
- data/lib/graphql/relay/page_info.rb +1 -0
- data/lib/graphql/relay/relation_connection.rb +3 -2
- data/lib/graphql/runtime_type_error.rb +4 -0
- data/lib/graphql/scalar_type.rb +2 -1
- data/lib/graphql/schema.rb +116 -26
- data/lib/graphql/schema/base_64_encoder.rb +14 -0
- data/lib/graphql/schema/build_from_definition.rb +4 -0
- data/lib/graphql/schema/catchall_middleware.rb +1 -0
- data/lib/graphql/schema/default_type_error.rb +15 -0
- data/lib/graphql/schema/instrumented_field_map.rb +1 -0
- data/lib/graphql/schema/invalid_type_error.rb +1 -0
- data/lib/graphql/schema/loader.rb +5 -1
- data/lib/graphql/schema/middleware_chain.rb +1 -0
- data/lib/graphql/schema/possible_types.rb +1 -0
- data/lib/graphql/schema/printer.rb +3 -2
- data/lib/graphql/schema/reduce_types.rb +1 -0
- data/lib/graphql/schema/rescue_middleware.rb +3 -2
- data/lib/graphql/schema/timeout_middleware.rb +1 -0
- data/lib/graphql/schema/type_expression.rb +1 -0
- data/lib/graphql/schema/type_map.rb +1 -0
- data/lib/graphql/schema/unique_within_type.rb +1 -0
- data/lib/graphql/schema/validation.rb +57 -1
- data/lib/graphql/schema/warden.rb +1 -0
- data/lib/graphql/static_validation.rb +1 -0
- data/lib/graphql/static_validation/all_rules.rb +1 -0
- data/lib/graphql/static_validation/arguments_validator.rb +1 -0
- data/lib/graphql/static_validation/literal_validator.rb +1 -0
- data/lib/graphql/static_validation/message.rb +1 -0
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -0
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +1 -0
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -0
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +1 -0
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +1 -0
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +1 -0
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +6 -3
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +1 -0
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +1 -0
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +1 -0
- data/lib/graphql/static_validation/rules/fragments_are_named.rb +1 -0
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -0
- data/lib/graphql/static_validation/rules/fragments_are_used.rb +1 -0
- data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -0
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +1 -0
- data/lib/graphql/static_validation/rules/subscription_root_exists.rb +1 -0
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +1 -0
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +1 -0
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +1 -0
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -0
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +1 -0
- data/lib/graphql/static_validation/type_stack.rb +1 -0
- data/lib/graphql/static_validation/validation_context.rb +2 -1
- data/lib/graphql/static_validation/validator.rb +2 -1
- data/lib/graphql/string_type.rb +1 -0
- data/lib/graphql/type_kinds.rb +1 -0
- data/lib/graphql/union_type.rb +13 -0
- data/lib/graphql/unresolved_type_error.rb +26 -5
- data/lib/graphql/version.rb +2 -1
- data/readme.md +1 -5
- data/spec/graphql/analysis/analyze_query_spec.rb +1 -0
- data/spec/graphql/analysis/field_usage_spec.rb +1 -0
- data/spec/graphql/analysis/max_query_complexity_spec.rb +1 -0
- data/spec/graphql/analysis/max_query_depth_spec.rb +1 -0
- data/spec/graphql/analysis/query_complexity_spec.rb +1 -0
- data/spec/graphql/analysis/query_depth_spec.rb +1 -0
- data/spec/graphql/argument_spec.rb +1 -0
- data/spec/graphql/base_type_spec.rb +13 -0
- data/spec/graphql/boolean_type_spec.rb +1 -0
- data/spec/graphql/compatibility/execution_specification_spec.rb +1 -0
- data/spec/graphql/compatibility/lazy_execution_specification_spec.rb +4 -0
- data/spec/graphql/compatibility/query_parser_specification_spec.rb +1 -0
- data/spec/graphql/compatibility/schema_parser_specification_spec.rb +1 -0
- data/spec/graphql/define/assign_argument_spec.rb +1 -0
- data/spec/graphql/define/instance_definable_spec.rb +1 -0
- data/spec/graphql/directive_spec.rb +1 -0
- data/spec/graphql/enum_type_spec.rb +10 -0
- data/spec/graphql/execution/execute_spec.rb +5 -0
- data/spec/graphql/execution/lazy_spec.rb +252 -0
- data/spec/graphql/execution/typecast_spec.rb +1 -0
- data/spec/graphql/execution_error_spec.rb +1 -0
- data/spec/graphql/field_spec.rb +17 -0
- data/spec/graphql/float_type_spec.rb +1 -0
- data/spec/graphql/id_type_spec.rb +1 -0
- data/spec/graphql/input_object_type_spec.rb +10 -0
- data/spec/graphql/int_type_spec.rb +1 -0
- data/spec/graphql/interface_type_spec.rb +10 -0
- data/spec/graphql/internal_representation/rewrite_spec.rb +1 -0
- data/spec/graphql/introspection/directive_type_spec.rb +1 -0
- data/spec/graphql/introspection/input_value_type_spec.rb +1 -0
- data/spec/graphql/introspection/introspection_query_spec.rb +1 -0
- data/spec/graphql/introspection/schema_type_spec.rb +1 -0
- data/spec/graphql/introspection/type_type_spec.rb +1 -0
- data/spec/graphql/language/definition_slice_spec.rb +1 -0
- data/spec/graphql/language/equality_spec.rb +1 -0
- data/spec/graphql/language/generation_spec.rb +1 -0
- data/spec/graphql/language/lexer_spec.rb +1 -0
- data/spec/graphql/language/nodes_spec.rb +1 -0
- data/spec/graphql/language/parser_spec.rb +1 -0
- data/spec/graphql/language/visitor_spec.rb +1 -0
- data/spec/graphql/list_type_spec.rb +1 -0
- data/spec/graphql/non_null_type_spec.rb +17 -0
- data/spec/graphql/object_type_spec.rb +19 -0
- data/spec/graphql/query/arguments_spec.rb +1 -0
- data/spec/graphql/query/context_spec.rb +1 -0
- data/spec/graphql/query/executor_spec.rb +1 -0
- data/spec/graphql/query/serial_execution/value_resolution_spec.rb +1 -0
- data/spec/graphql/query/variables_spec.rb +1 -0
- data/spec/graphql/query_spec.rb +25 -0
- data/spec/graphql/relay/array_connection_spec.rb +1 -0
- data/spec/graphql/relay/base_connection_spec.rb +33 -4
- data/spec/graphql/relay/connection_field_spec.rb +1 -0
- data/spec/graphql/relay/connection_type_spec.rb +1 -0
- data/spec/graphql/relay/mutation_spec.rb +6 -0
- data/spec/graphql/relay/node_spec.rb +1 -0
- data/spec/graphql/relay/page_info_spec.rb +1 -0
- data/spec/graphql/relay/relation_connection_spec.rb +1 -0
- data/spec/graphql/scalar_type_spec.rb +1 -0
- data/spec/graphql/schema/build_from_definition_spec.rb +9 -1
- data/spec/graphql/schema/catchall_middleware_spec.rb +1 -0
- data/spec/graphql/schema/loader_spec.rb +7 -0
- data/spec/graphql/schema/middleware_chain_spec.rb +1 -0
- data/spec/graphql/schema/printer_spec.rb +1 -0
- data/spec/graphql/schema/reduce_types_spec.rb +1 -0
- data/spec/graphql/schema/rescue_middleware_spec.rb +1 -0
- data/spec/graphql/schema/timeout_middleware_spec.rb +1 -0
- data/spec/graphql/schema/type_expression_spec.rb +1 -0
- data/spec/graphql/schema/unique_within_type_spec.rb +1 -0
- data/spec/graphql/schema/validation_spec.rb +55 -0
- data/spec/graphql/schema/warden_spec.rb +1 -0
- data/spec/graphql/schema_spec.rb +39 -0
- data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +515 -31
- data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/fragments_are_named_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/mutation_root_exists_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/subscription_root_exists_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/unique_directives_per_location_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +1 -0
- data/spec/graphql/static_validation/type_stack_spec.rb +1 -0
- data/spec/graphql/static_validation/validator_spec.rb +1 -0
- data/spec/graphql/string_type_spec.rb +1 -0
- data/spec/graphql/union_type_spec.rb +11 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/support/dairy_app.rb +1 -0
- data/spec/support/dairy_data.rb +1 -0
- data/spec/support/minimum_input_object.rb +1 -0
- data/spec/support/star_wars_data.rb +1 -0
- data/spec/support/star_wars_schema.rb +30 -7
- data/spec/support/static_validation_helpers.rb +1 -0
- metadata +24 -5
- data/lib/graphql/internal_representation/selections.rb +0 -41
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "graphql/execution/lazy/lazy_method_map"
|
3
|
+
require "graphql/execution/lazy/resolve"
|
4
|
+
module GraphQL
|
5
|
+
module Execution
|
6
|
+
# This wraps a value which is available, but not yet calculated, like a promise or future.
|
7
|
+
#
|
8
|
+
# Calling `#value` will trigger calculation & return the "lazy" value.
|
9
|
+
#
|
10
|
+
# This is an itty-bitty promise-like object, with key differences:
|
11
|
+
# - It has only two states, not-resolved and resolved
|
12
|
+
# - It has no error-catching functionality
|
13
|
+
class Lazy
|
14
|
+
# Traverse `val`, lazily resolving any values along the way
|
15
|
+
# @param val [Object] A data structure containing mixed plain values and `Lazy` instances
|
16
|
+
# @return void
|
17
|
+
def self.resolve(val)
|
18
|
+
Resolve.resolve(val)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Create a {Lazy} which will get its inner value by calling the block
|
22
|
+
# @param target [Object]
|
23
|
+
# @param method_name [Symbol]
|
24
|
+
# @param get_value_func [Proc] a block to get the inner value (later)
|
25
|
+
def initialize(target = nil, method_name = nil, &get_value_func)
|
26
|
+
if block_given?
|
27
|
+
@get_value_func = get_value_func
|
28
|
+
else
|
29
|
+
@target = target
|
30
|
+
@method_name = method_name
|
31
|
+
end
|
32
|
+
@resolved = false
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [Object] The wrapped value, calling the lazy block if necessary
|
36
|
+
def value
|
37
|
+
if !@resolved
|
38
|
+
@resolved = true
|
39
|
+
if @get_value_func
|
40
|
+
@value = @get_value_func.call
|
41
|
+
else
|
42
|
+
@value = @target.public_send(@method_name)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
@value
|
46
|
+
rescue GraphQL::ExecutionError => err
|
47
|
+
@resolved = true
|
48
|
+
@value = err
|
49
|
+
end
|
50
|
+
|
51
|
+
# @return [Lazy] A {Lazy} whose value depends on another {Lazy}, plus any transformations in `block`
|
52
|
+
def then(&block)
|
53
|
+
self.class.new {
|
54
|
+
next_val = block.call(value)
|
55
|
+
}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module Execution
|
4
|
+
class Lazy
|
5
|
+
# {GraphQL::Schema} uses this to match returned values to lazy resolution methods.
|
6
|
+
# Methods may be registered for classes, they apply to its subclasses also.
|
7
|
+
# The result of this lookup is cached for future resolutions.
|
8
|
+
class LazyMethodMap
|
9
|
+
def initialize
|
10
|
+
@storage = Hash.new do |h, value_class|
|
11
|
+
registered_superclass = h.each_key.find { |lazy_class| value_class < lazy_class }
|
12
|
+
if registered_superclass.nil?
|
13
|
+
h[value_class] = nil
|
14
|
+
else
|
15
|
+
h[value_class] = h[registered_superclass]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param lazy_class [Class] A class which represents a lazy value (subclasses may also be used)
|
21
|
+
# @param lazy_value_method [Symbol] The method to call on this class to get its value
|
22
|
+
def set(lazy_class, lazy_value_method)
|
23
|
+
@storage[lazy_class] = lazy_value_method
|
24
|
+
end
|
25
|
+
|
26
|
+
# @param value [Object] an object which may have a `lazy_value_method` registered for its class or superclasses
|
27
|
+
# @return [Symbol, nil] The `lazy_value_method` for this object, or nil
|
28
|
+
def get(value)
|
29
|
+
@storage[value.class]
|
30
|
+
end
|
31
|
+
|
32
|
+
def each
|
33
|
+
@storage.each { |k, v| yield(k,v) }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module Execution
|
4
|
+
class Lazy
|
5
|
+
# Helpers for dealing with data structures containing {Lazy} instances
|
6
|
+
module Resolve
|
7
|
+
# Mutate `value`, replacing {Lazy} instances in place with their resolved values
|
8
|
+
# @return [void]
|
9
|
+
def self.resolve(value)
|
10
|
+
lazies = resolve_in_place(value)
|
11
|
+
deep_sync(lazies)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.resolve_in_place(value)
|
15
|
+
lazies = []
|
16
|
+
|
17
|
+
each_lazy(value) do |field_result|
|
18
|
+
inner_lazy = field_result.value.then do |inner_v|
|
19
|
+
field_result.value = inner_v
|
20
|
+
resolve_in_place(inner_v)
|
21
|
+
end
|
22
|
+
lazies.push(inner_lazy)
|
23
|
+
end
|
24
|
+
|
25
|
+
Lazy.new { lazies.map(&:value) }
|
26
|
+
end
|
27
|
+
|
28
|
+
# If `value` is a collection, call `block`
|
29
|
+
# with any {Lazy} instances in the collection
|
30
|
+
# @return [void]
|
31
|
+
def self.each_lazy(value, &block)
|
32
|
+
case value
|
33
|
+
when SelectionResult
|
34
|
+
value.each do |key, field_result|
|
35
|
+
each_lazy(field_result, &block)
|
36
|
+
end
|
37
|
+
when Array
|
38
|
+
value.each do |field_result|
|
39
|
+
each_lazy(field_result, &block)
|
40
|
+
end
|
41
|
+
when FieldResult
|
42
|
+
field_value = value.value
|
43
|
+
if field_value.is_a?(Lazy)
|
44
|
+
yield(value)
|
45
|
+
else
|
46
|
+
each_lazy(field_value, &block)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Traverse `val`, triggering resolution for each {Lazy}.
|
52
|
+
# These {Lazy}s are expected to mutate their owner data structures
|
53
|
+
# during resolution! (They're created with the `.then` calls in `resolve_in_place`).
|
54
|
+
# @return [void]
|
55
|
+
def self.deep_sync(val)
|
56
|
+
case val
|
57
|
+
when Lazy
|
58
|
+
deep_sync(val.value)
|
59
|
+
when Array
|
60
|
+
val.each { |v| deep_sync(v.value) }
|
61
|
+
when Hash
|
62
|
+
val.each { |k, v| deep_sync(v.value) }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module Execution
|
4
|
+
# A set of key-value pairs suitable for a GraphQL response.
|
5
|
+
class SelectionResult
|
6
|
+
def initialize
|
7
|
+
@storage = {}
|
8
|
+
@owner = nil
|
9
|
+
@invalid_null = false
|
10
|
+
end
|
11
|
+
|
12
|
+
# @param key [String] The name for this value in the result
|
13
|
+
# @param field_result [FieldResult] The result for this field
|
14
|
+
def set(key, field_result)
|
15
|
+
@storage[key] = field_result
|
16
|
+
end
|
17
|
+
|
18
|
+
# @param key [String] The name of an already-defined result
|
19
|
+
# @return [FieldResult] The result for this field
|
20
|
+
def fetch(key)
|
21
|
+
@storage.fetch(key)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Visit each key-result pair in this result
|
25
|
+
def each
|
26
|
+
@storage.each do |key, field_res|
|
27
|
+
yield(key, field_res)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [Hash] A plain Hash representation of this result
|
32
|
+
def to_h
|
33
|
+
if @invalid_null
|
34
|
+
nil
|
35
|
+
else
|
36
|
+
flatten(self)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# A field has been unexpectedly nullified.
|
41
|
+
# Tell the owner {FieldResult} if it is present.
|
42
|
+
# Record {#invalid_null} in case an owner is added later.
|
43
|
+
def propagate_null
|
44
|
+
if @owner
|
45
|
+
@owner.value = GraphQL::Execution::Execute::PROPAGATE_NULL
|
46
|
+
end
|
47
|
+
@invalid_null = true
|
48
|
+
end
|
49
|
+
|
50
|
+
# @return [Boolean] True if this selection has been nullified by a null child
|
51
|
+
def invalid_null?
|
52
|
+
@invalid_null
|
53
|
+
end
|
54
|
+
|
55
|
+
# @param field_result [FieldResult] The field that this selection belongs to (used for propagating nulls)
|
56
|
+
def owner=(field_result)
|
57
|
+
if @owner
|
58
|
+
raise("Can't change owners of SelectionResult")
|
59
|
+
else
|
60
|
+
@owner = field_result
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def flatten(obj)
|
67
|
+
case obj
|
68
|
+
when SelectionResult
|
69
|
+
flattened = {}
|
70
|
+
obj.each do |key, val|
|
71
|
+
flattened[key] = flatten(val)
|
72
|
+
end
|
73
|
+
flattened
|
74
|
+
when Array
|
75
|
+
obj.map { |v| flatten(v) }
|
76
|
+
when FieldResult
|
77
|
+
flatten(obj.value)
|
78
|
+
else
|
79
|
+
obj
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module GraphQL
|
2
3
|
module Execution
|
3
4
|
# GraphQL object `{value, current_type}` can be cast to `potential_type` when:
|
@@ -12,10 +13,9 @@ module GraphQL
|
|
12
13
|
#
|
13
14
|
# This is used for checking whether fragments apply to an object.
|
14
15
|
#
|
15
|
-
# @param [
|
16
|
-
# @param [GraphQL::BaseType]
|
17
|
-
# @param [GraphQL::
|
18
|
-
# @param [GraphQL::Query::Context] the context for the current query
|
16
|
+
# @param current_type [GraphQL::BaseType] the type which GraphQL is using now
|
17
|
+
# @param potential_type [GraphQL::BaseType] can this type be used from here?
|
18
|
+
# @param query_ctx [GraphQL::Query::Context] the context for the current query
|
19
19
|
# @return [Boolean] true if `value` be evaluated as a `potential_type`
|
20
20
|
def self.compatible?(current_type, potential_type, query_ctx)
|
21
21
|
if current_type == potential_type
|
data/lib/graphql/field.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "graphql/field/resolve"
|
2
3
|
|
3
4
|
module GraphQL
|
@@ -121,46 +122,65 @@ module GraphQL
|
|
121
122
|
class Field
|
122
123
|
include GraphQL::Define::InstanceDefinable
|
123
124
|
accepts_definitions :name, :description, :deprecation_reason,
|
124
|
-
:resolve, :
|
125
|
+
:resolve, :lazy_resolve,
|
126
|
+
:type, :arguments,
|
125
127
|
:property, :hash_key, :complexity, :mutation,
|
126
128
|
:relay_node_field,
|
127
129
|
argument: GraphQL::Define::AssignArgument
|
128
130
|
|
129
|
-
|
130
|
-
attr_accessor :name, :deprecation_reason, :description, :property, :hash_key, :mutation, :arguments, :complexity
|
131
|
-
|
132
|
-
# @return [Boolean] True if this is the Relay find-by-id field
|
133
|
-
attr_accessor :relay_node_field
|
134
|
-
|
135
131
|
ensure_defined(
|
136
132
|
:name, :deprecation_reason, :description, :description=, :property, :hash_key, :mutation, :arguments, :complexity,
|
137
|
-
:resolve, :resolve=, :
|
133
|
+
:resolve, :resolve=, :lazy_resolve, :lazy_resolve=, :lazy_resolve_proc,
|
134
|
+
:type, :type=, :name=, :property=, :hash_key=,
|
138
135
|
:relay_node_field,
|
139
136
|
)
|
140
137
|
|
141
|
-
#
|
142
|
-
|
138
|
+
# @return [Boolean] True if this is the Relay find-by-id field
|
139
|
+
attr_accessor :relay_node_field
|
140
|
+
|
141
|
+
# @return [<#call(obj, args, ctx)>] A proc-like object which can be called to return the field's value
|
143
142
|
attr_reader :resolve_proc
|
144
143
|
|
145
|
-
#
|
146
|
-
|
144
|
+
# @return [<#call(obj, args, ctx)>] A proc-like object which can be called trigger a lazy resolution
|
145
|
+
attr_reader :lazy_resolve_proc
|
146
|
+
|
147
|
+
# @return [String] The name of this field on its {GraphQL::ObjectType} (or {GraphQL::InterfaceType})
|
148
|
+
attr_accessor :name
|
149
|
+
|
150
|
+
# @return [String, nil] The client-facing description of this field
|
151
|
+
attr_accessor :description
|
152
|
+
|
153
|
+
# @return [String, nil] The client-facing reason why this field is deprecated (if present, the field is deprecated)
|
154
|
+
attr_accessor :deprecation_reason
|
155
|
+
|
156
|
+
# @return [Hash<String => GraphQL::Argument>] Map String argument names to their {GraphQL::Argument} implementations
|
157
|
+
attr_accessor :arguments
|
147
158
|
|
148
|
-
#
|
149
|
-
|
159
|
+
# @return [GraphQL::Relay::Mutation, nil] The mutation this field was derived from, if it was derived from a mutation
|
160
|
+
attr_accessor :mutation
|
150
161
|
|
151
|
-
#
|
152
|
-
|
162
|
+
# @return [Numeric, Proc] The complexity for this field (default: 1), as a constant or a proc like `->(query_ctx, args, child_complexity) { } # Numeric`
|
163
|
+
attr_accessor :complexity
|
153
164
|
|
154
|
-
#
|
155
|
-
|
165
|
+
# @return [Symbol, nil] The method to call on `obj` to return this field (overrides {#name} if present)
|
166
|
+
attr_accessor :property
|
167
|
+
|
168
|
+
# @return [Object, nil] The key to access with `obj.[]` to resolve this field (overrides {#name} if present)
|
169
|
+
attr_accessor :hash_key
|
156
170
|
|
157
171
|
def initialize
|
158
172
|
@complexity = 1
|
159
173
|
@arguments = {}
|
160
174
|
@resolve_proc = build_default_resolver
|
175
|
+
@lazy_resolve_proc = DefaultLazyResolve
|
161
176
|
@relay_node_field = false
|
162
177
|
end
|
163
178
|
|
179
|
+
def initialize_copy(other)
|
180
|
+
super
|
181
|
+
@arguments = other.arguments.dup
|
182
|
+
end
|
183
|
+
|
164
184
|
# Get a value for this field
|
165
185
|
# @example resolving a field value
|
166
186
|
# field.resolve(obj, args, ctx)
|
@@ -217,10 +237,40 @@ module GraphQL
|
|
217
237
|
"<Field name:#{name || "not-named"} desc:#{description} resolve:#{resolve_proc}>"
|
218
238
|
end
|
219
239
|
|
240
|
+
# If {#resolve} returned and object which should be handled lazily,
|
241
|
+
# this method will be called later force the object to return its value.
|
242
|
+
# @param obj [Object] The {#resolve}-provided object, registered with {Schema#lazy_resolve}
|
243
|
+
# @param args [GraphQL::Query::Arguments] Arguments to this field
|
244
|
+
# @param ctx [GraphQL::Query::Context] Context for this field
|
245
|
+
# @return [Object] The result of calling the registered method on `obj`
|
246
|
+
def lazy_resolve(obj, args, ctx)
|
247
|
+
@lazy_resolve_proc.call(obj, args, ctx)
|
248
|
+
end
|
249
|
+
|
250
|
+
# Assign a new resolve proc to this field. Used for {#lazy_resolve}
|
251
|
+
def lazy_resolve=(new_lazy_resolve_proc)
|
252
|
+
@lazy_resolve_proc = new_lazy_resolve_proc
|
253
|
+
end
|
254
|
+
|
255
|
+
# Prepare a lazy value for this field. It may be `then`-ed and resolved later.
|
256
|
+
# @return [GraphQL::Execution::Lazy] A lazy wrapper around `obj` and its registered method name
|
257
|
+
def prepare_lazy(obj, args, ctx)
|
258
|
+
GraphQL::Execution::Lazy.new {
|
259
|
+
lazy_resolve(obj, args, ctx)
|
260
|
+
}
|
261
|
+
end
|
262
|
+
|
220
263
|
private
|
221
264
|
|
222
265
|
def build_default_resolver
|
223
266
|
GraphQL::Field::Resolve.create_proc(self)
|
224
267
|
end
|
268
|
+
|
269
|
+
module DefaultLazyResolve
|
270
|
+
def self.call(obj, args, ctx)
|
271
|
+
method_name = ctx.schema.lazy_method_name(obj)
|
272
|
+
obj.public_send(method_name)
|
273
|
+
end
|
274
|
+
end
|
225
275
|
end
|
226
276
|
end
|
data/lib/graphql/float_type.rb
CHANGED
data/lib/graphql/id_type.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
GraphQL::ID_TYPE = GraphQL::ScalarType.define do
|
2
3
|
name "ID"
|
3
4
|
description "Represents a unique identifier that is Base64 obfuscated. It is often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `\"VXNlci0xMA==\"`) or integer (such as `4`) input value will be accepted as an ID."
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module GraphQL
|
2
3
|
# {InputObjectType}s are key-value inputs for fields.
|
3
4
|
#
|
@@ -44,6 +45,11 @@ module GraphQL
|
|
44
45
|
@arguments = {}
|
45
46
|
end
|
46
47
|
|
48
|
+
def initialize_copy(other)
|
49
|
+
super
|
50
|
+
@arguments = other.arguments.dup
|
51
|
+
end
|
52
|
+
|
47
53
|
def kind
|
48
54
|
GraphQL::TypeKinds::INPUT_OBJECT
|
49
55
|
end
|
data/lib/graphql/int_type.rb
CHANGED