graphql 1.2.6 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module Compatibility
|
4
|
+
module ExecutionSpecification
|
5
|
+
module CounterSchema
|
6
|
+
def self.build(execution_strategy)
|
7
|
+
counter_type = nil
|
8
|
+
schema = nil
|
9
|
+
|
10
|
+
has_count_interface = GraphQL::InterfaceType.define do
|
11
|
+
name "HasCount"
|
12
|
+
field :count, types.Int
|
13
|
+
field :counter, ->{ counter_type }
|
14
|
+
end
|
15
|
+
|
16
|
+
counter_type = GraphQL::ObjectType.define do
|
17
|
+
name "Counter"
|
18
|
+
interfaces [has_count_interface]
|
19
|
+
field :count, types.Int, resolve: ->(o,a,c) { schema.metadata[:count] += 1 }
|
20
|
+
field :counter, has_count_interface, resolve: ->(o,a,c) { :counter }
|
21
|
+
end
|
22
|
+
|
23
|
+
alt_counter_type = GraphQL::ObjectType.define do
|
24
|
+
name "AltCounter"
|
25
|
+
interfaces [has_count_interface]
|
26
|
+
field :count, types.Int, resolve: ->(o,a,c) { schema.metadata[:count] += 1 }
|
27
|
+
field :counter, has_count_interface, resolve: ->(o,a,c) { :counter }
|
28
|
+
end
|
29
|
+
|
30
|
+
has_counter_interface = GraphQL::InterfaceType.define do
|
31
|
+
name "HasCounter"
|
32
|
+
field :counter, counter_type
|
33
|
+
end
|
34
|
+
|
35
|
+
query_type = GraphQL::ObjectType.define do
|
36
|
+
name "Query"
|
37
|
+
interfaces [has_counter_interface]
|
38
|
+
field :counter, has_count_interface, resolve: ->(o,a,c) { :counter }
|
39
|
+
end
|
40
|
+
|
41
|
+
schema = GraphQL::Schema.define(
|
42
|
+
query: query_type,
|
43
|
+
resolve_type: ->(o, c) { o == :counter ? counter_type : nil },
|
44
|
+
orphan_types: [alt_counter_type],
|
45
|
+
query_execution_strategy: execution_strategy,
|
46
|
+
)
|
47
|
+
schema.metadata[:count] = 0
|
48
|
+
schema
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,195 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module Compatibility
|
4
|
+
module ExecutionSpecification
|
5
|
+
module SpecificationSchema
|
6
|
+
BOGUS_NODE = OpenStruct.new({ bogus: true })
|
7
|
+
|
8
|
+
DATA = {
|
9
|
+
"1001" => OpenStruct.new({
|
10
|
+
name: "Fannie Lou Hamer",
|
11
|
+
birthdate: Time.new(1917, 10, 6),
|
12
|
+
organization_ids: [],
|
13
|
+
}),
|
14
|
+
"1002" => OpenStruct.new({
|
15
|
+
name: "John Lewis",
|
16
|
+
birthdate: Time.new(1940, 2, 21),
|
17
|
+
organization_ids: ["2001"],
|
18
|
+
}),
|
19
|
+
"1003" => OpenStruct.new({
|
20
|
+
name: "Diane Nash",
|
21
|
+
birthdate: Time.new(1938, 5, 15),
|
22
|
+
organization_ids: ["2001", "2002"],
|
23
|
+
}),
|
24
|
+
"1004" => OpenStruct.new({
|
25
|
+
name: "Ralph Abernathy",
|
26
|
+
birthdate: Time.new(1926, 3, 11),
|
27
|
+
organization_ids: ["2002"],
|
28
|
+
}),
|
29
|
+
"2001" => OpenStruct.new({
|
30
|
+
name: "SNCC",
|
31
|
+
leader_id: nil, # fail on purpose
|
32
|
+
}),
|
33
|
+
"2002" => OpenStruct.new({
|
34
|
+
name: "SCLC",
|
35
|
+
leader_id: "1004",
|
36
|
+
}),
|
37
|
+
"2003" => BOGUS_NODE,
|
38
|
+
}
|
39
|
+
|
40
|
+
# A list object must implement #each
|
41
|
+
class CustomCollection
|
42
|
+
def initialize(storage)
|
43
|
+
@storage = storage
|
44
|
+
end
|
45
|
+
|
46
|
+
def each
|
47
|
+
@storage.each { |i| yield(i) }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
module TestMiddleware
|
52
|
+
def self.call(parent_type, parent_object, field_definition, field_args, query_context, next_middleware)
|
53
|
+
query_context[:middleware_log] && query_context[:middleware_log] << field_definition.name
|
54
|
+
next_middleware.call
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.build(execution_strategy)
|
59
|
+
organization_type = nil
|
60
|
+
|
61
|
+
timestamp_type = GraphQL::ScalarType.define do
|
62
|
+
name "Timestamp"
|
63
|
+
coerce_input ->(value) { Time.at(value.to_i) }
|
64
|
+
coerce_result ->(value) { value.to_i }
|
65
|
+
end
|
66
|
+
|
67
|
+
named_entity_interface_type = GraphQL::InterfaceType.define do
|
68
|
+
name "NamedEntity"
|
69
|
+
field :name, !types.String
|
70
|
+
end
|
71
|
+
|
72
|
+
person_type = GraphQL::ObjectType.define do
|
73
|
+
name "Person"
|
74
|
+
interfaces [named_entity_interface_type]
|
75
|
+
field :name, !types.String
|
76
|
+
field :birthdate, timestamp_type
|
77
|
+
field :age, types.Int do
|
78
|
+
argument :on, !timestamp_type
|
79
|
+
resolve ->(obj, args, ctx) {
|
80
|
+
if obj.birthdate.nil?
|
81
|
+
nil
|
82
|
+
else
|
83
|
+
age_on = args[:on]
|
84
|
+
age_years = age_on.year - obj.birthdate.year
|
85
|
+
this_year_birthday = Time.new(age_on.year, obj.birthdate.month, obj.birthdate.day)
|
86
|
+
if this_year_birthday > age_on
|
87
|
+
age_years -= 1
|
88
|
+
end
|
89
|
+
end
|
90
|
+
age_years
|
91
|
+
}
|
92
|
+
end
|
93
|
+
field :organizations, types[organization_type] do
|
94
|
+
resolve ->(obj, args, ctx) {
|
95
|
+
CustomCollection.new(obj.organization_ids.map { |id| DATA[id] })
|
96
|
+
}
|
97
|
+
end
|
98
|
+
field :first_organization, !organization_type do
|
99
|
+
resolve ->(obj, args, ctx) {
|
100
|
+
DATA[obj.organization_ids.first]
|
101
|
+
}
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
organization_type = GraphQL::ObjectType.define do
|
106
|
+
name "Organization"
|
107
|
+
interfaces [named_entity_interface_type]
|
108
|
+
field :name, !types.String
|
109
|
+
field :leader, !person_type do
|
110
|
+
resolve ->(obj, args, ctx) {
|
111
|
+
DATA[obj.leader_id] || (ctx[:return_error] ? ExecutionError.new("Error on Nullable") : nil)
|
112
|
+
}
|
113
|
+
end
|
114
|
+
field :returnedError, types.String do
|
115
|
+
resolve ->(o, a, c) {
|
116
|
+
GraphQL::ExecutionError.new("This error was returned")
|
117
|
+
}
|
118
|
+
end
|
119
|
+
field :raisedError, types.String do
|
120
|
+
resolve ->(o, a, c) {
|
121
|
+
raise GraphQL::ExecutionError.new("This error was raised")
|
122
|
+
}
|
123
|
+
end
|
124
|
+
|
125
|
+
field :nodePresence, !types[!types.Boolean] do
|
126
|
+
resolve ->(o, a, ctx) {
|
127
|
+
[
|
128
|
+
ctx.irep_node.is_a?(GraphQL::InternalRepresentation::Node),
|
129
|
+
ctx.ast_node.is_a?(GraphQL::Language::Nodes::AbstractNode),
|
130
|
+
false, # just testing
|
131
|
+
]
|
132
|
+
}
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
node_union_type = GraphQL::UnionType.define do
|
137
|
+
name "Node"
|
138
|
+
possible_types [person_type, organization_type]
|
139
|
+
end
|
140
|
+
|
141
|
+
query_type = GraphQL::ObjectType.define do
|
142
|
+
name "Query"
|
143
|
+
field :node, node_union_type do
|
144
|
+
argument :id, !types.ID
|
145
|
+
resolve ->(obj, args, ctx) {
|
146
|
+
obj[args[:id]]
|
147
|
+
}
|
148
|
+
end
|
149
|
+
|
150
|
+
field :requiredNode, node_union_type.to_non_null_type do
|
151
|
+
argument :id, !types.ID
|
152
|
+
resolve ->(obj, args, ctx) {
|
153
|
+
obj[args[:id]]
|
154
|
+
}
|
155
|
+
end
|
156
|
+
|
157
|
+
field :organization, !organization_type do
|
158
|
+
argument :id, !types.ID
|
159
|
+
resolve ->(obj, args, ctx) {
|
160
|
+
args[:id].start_with?("2") && obj[args[:id]]
|
161
|
+
}
|
162
|
+
end
|
163
|
+
|
164
|
+
field :organizations, types[organization_type] do
|
165
|
+
resolve ->(obj, args, ctx) {
|
166
|
+
[obj["2001"], obj["2002"]]
|
167
|
+
}
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
GraphQL::Schema.define do
|
172
|
+
query_execution_strategy execution_strategy
|
173
|
+
query query_type
|
174
|
+
|
175
|
+
resolve_type ->(obj, ctx) {
|
176
|
+
if obj.respond_to?(:birthdate)
|
177
|
+
person_type
|
178
|
+
elsif obj.respond_to?(:leader_id)
|
179
|
+
organization_type
|
180
|
+
else
|
181
|
+
nil
|
182
|
+
end
|
183
|
+
}
|
184
|
+
|
185
|
+
type_error ->(err, ctx) {
|
186
|
+
ctx[:type_errors] && (ctx[:type_errors] << err.value)
|
187
|
+
ctx[:gobble] || GraphQL::Schema::DefaultTypeError.call(err, ctx)
|
188
|
+
}
|
189
|
+
middleware(TestMiddleware)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "graphql/compatibility/lazy_execution_specification/lazy_schema"
|
3
|
+
|
4
|
+
module GraphQL
|
5
|
+
module Compatibility
|
6
|
+
module LazyExecutionSpecification
|
7
|
+
# @param execution_strategy [<#new, #execute>] An execution strategy class
|
8
|
+
# @return [Class<Minitest::Test>] A test suite for this execution strategy
|
9
|
+
def self.build_suite(execution_strategy)
|
10
|
+
Class.new(Minitest::Test) do
|
11
|
+
class << self
|
12
|
+
attr_accessor :lazy_schema
|
13
|
+
end
|
14
|
+
|
15
|
+
self.lazy_schema = LazySchema.build(execution_strategy)
|
16
|
+
|
17
|
+
def test_it_resolves_lazy_values
|
18
|
+
pushes = []
|
19
|
+
query_str = %|
|
20
|
+
{
|
21
|
+
p1: push(value: 1) {
|
22
|
+
value
|
23
|
+
}
|
24
|
+
p2: push(value: 2) {
|
25
|
+
push(value: 3) {
|
26
|
+
value
|
27
|
+
}
|
28
|
+
}
|
29
|
+
p3: push(value: 4) {
|
30
|
+
push(value: 5) {
|
31
|
+
value
|
32
|
+
}
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
|
36
|
+
res = self.class.lazy_schema.execute(query_str, context: {pushes: pushes})
|
37
|
+
|
38
|
+
expected_data = {
|
39
|
+
"p1"=>{"value"=>1},
|
40
|
+
"p2"=>{"push"=>{"value"=>3}},
|
41
|
+
"p3"=>{"push"=>{"value"=>5}},
|
42
|
+
}
|
43
|
+
assert_equal expected_data, res["data"]
|
44
|
+
|
45
|
+
expected_pushes = [
|
46
|
+
[1,2,4], # first level
|
47
|
+
[3,5], # second level
|
48
|
+
]
|
49
|
+
assert_equal expected_pushes, pushes
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_it_maintains_path
|
53
|
+
query_str = %|
|
54
|
+
{
|
55
|
+
push(value: 2) {
|
56
|
+
push(value: 3) {
|
57
|
+
fail1: push(value: 14) {
|
58
|
+
value
|
59
|
+
}
|
60
|
+
fail2: push(value: 14) {
|
61
|
+
value
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
|
67
|
+
res = self.class.lazy_schema.execute(query_str, context: {pushes: []})
|
68
|
+
assert_equal nil, res["data"]
|
69
|
+
assert_equal 2, res["errors"].length
|
70
|
+
assert_equal ["push", "push", "fail1", "value"], res["errors"][0]["path"]
|
71
|
+
assert_equal ["push", "push", "fail2", "value"], res["errors"][1]["path"]
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_it_resolves_mutation_values_eagerly
|
75
|
+
pushes = []
|
76
|
+
query_str = %|
|
77
|
+
mutation {
|
78
|
+
p1: push(value: 1) {
|
79
|
+
value
|
80
|
+
}
|
81
|
+
p2: push(value: 2) {
|
82
|
+
push(value: 3) {
|
83
|
+
value
|
84
|
+
}
|
85
|
+
}
|
86
|
+
p3: push(value: 4) {
|
87
|
+
p5: push(value: 5) {
|
88
|
+
value
|
89
|
+
}
|
90
|
+
p6: push(value: 6) {
|
91
|
+
value
|
92
|
+
}
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
|
96
|
+
res = self.class.lazy_schema.execute(query_str, context: {pushes: pushes})
|
97
|
+
|
98
|
+
expected_data = {
|
99
|
+
"p1"=>{"value"=>1},
|
100
|
+
"p2"=>{"push"=>{"value"=>3}},
|
101
|
+
"p3"=>{"p5"=>{"value"=>5},"p6"=>{"value"=>6}},
|
102
|
+
}
|
103
|
+
assert_equal expected_data, res["data"]
|
104
|
+
|
105
|
+
expected_pushes = [
|
106
|
+
[1], # first operation
|
107
|
+
[2], [3], # second operation
|
108
|
+
[4], [5, 6], # third operation
|
109
|
+
]
|
110
|
+
assert_equal expected_pushes, pushes
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_it_resolves_lazy_connections
|
114
|
+
pushes = []
|
115
|
+
query_str = %|
|
116
|
+
{
|
117
|
+
pushes(values: [1,2,3]) {
|
118
|
+
edges {
|
119
|
+
node {
|
120
|
+
value
|
121
|
+
push(value: 4) {
|
122
|
+
value
|
123
|
+
}
|
124
|
+
}
|
125
|
+
}
|
126
|
+
}
|
127
|
+
}
|
128
|
+
|
|
129
|
+
res = self.class.lazy_schema.execute(query_str, context: {pushes: pushes})
|
130
|
+
|
131
|
+
expected_edges = [
|
132
|
+
{"node"=>{"value"=>1, "push"=>{"value"=>4}}},
|
133
|
+
{"node"=>{"value"=>2, "push"=>{"value"=>4}}},
|
134
|
+
{"node"=>{"value"=>3, "push"=>{"value"=>4}}},
|
135
|
+
]
|
136
|
+
assert_equal expected_edges, res["data"]["pushes"]["edges"]
|
137
|
+
assert_equal [[1, 2, 3], [4, 4, 4]], pushes
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_it_calls_lazy_resolve_instrumentation
|
141
|
+
query_str = %|
|
142
|
+
{
|
143
|
+
p1: push(value: 1) {
|
144
|
+
value
|
145
|
+
}
|
146
|
+
p2: push(value: 2) {
|
147
|
+
push(value: 3) {
|
148
|
+
value
|
149
|
+
}
|
150
|
+
}
|
151
|
+
pushes(values: [1,2,3]) {
|
152
|
+
edges {
|
153
|
+
node {
|
154
|
+
value
|
155
|
+
push(value: 4) {
|
156
|
+
value
|
157
|
+
}
|
158
|
+
}
|
159
|
+
}
|
160
|
+
}
|
161
|
+
}
|
162
|
+
|
|
163
|
+
|
164
|
+
log = []
|
165
|
+
res = self.class.lazy_schema.execute(query_str, context: {lazy_instrumentation: log, pushes: []})
|
166
|
+
expected_log = [
|
167
|
+
"PUSH",
|
168
|
+
"Query.push: 1",
|
169
|
+
"Query.push: 2",
|
170
|
+
"PUSH",
|
171
|
+
"LazyPush.push: 3",
|
172
|
+
"LazyPushEdge.node: 1",
|
173
|
+
"LazyPushEdge.node: 2",
|
174
|
+
"LazyPushEdge.node: 3",
|
175
|
+
"PUSH",
|
176
|
+
"LazyPush.push: 4",
|
177
|
+
"LazyPush.push: 4",
|
178
|
+
"LazyPush.push: 4",
|
179
|
+
]
|
180
|
+
assert_equal expected_log, log
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module Compatibility
|
4
|
+
module LazyExecutionSpecification
|
5
|
+
module LazySchema
|
6
|
+
class LazyPush
|
7
|
+
attr_reader :value
|
8
|
+
def initialize(ctx, value)
|
9
|
+
if value == 13
|
10
|
+
@value = nil
|
11
|
+
elsif value == 14
|
12
|
+
@value = GraphQL::ExecutionError.new("oops!")
|
13
|
+
else
|
14
|
+
@value = value
|
15
|
+
end
|
16
|
+
@context = ctx
|
17
|
+
pushes = @context[:lazy_pushes] ||= []
|
18
|
+
pushes << @value
|
19
|
+
end
|
20
|
+
|
21
|
+
def push
|
22
|
+
if @context[:lazy_pushes].include?(@value)
|
23
|
+
@context[:lazy_instrumentation] && @context[:lazy_instrumentation] << "PUSH"
|
24
|
+
@context[:pushes] << @context[:lazy_pushes]
|
25
|
+
@context[:lazy_pushes] = []
|
26
|
+
end
|
27
|
+
self
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class LazyPushCollection
|
32
|
+
def initialize(ctx, values)
|
33
|
+
@ctx = ctx
|
34
|
+
@values = values
|
35
|
+
end
|
36
|
+
|
37
|
+
def push
|
38
|
+
@values.map { |v| LazyPush.new(@ctx, v) }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
module LazyInstrumentation
|
43
|
+
def self.instrument(type, field)
|
44
|
+
prev_lazy_resolve = field.lazy_resolve_proc
|
45
|
+
field.redefine {
|
46
|
+
lazy_resolve ->(o, a, c) {
|
47
|
+
result = prev_lazy_resolve.call(o, a, c)
|
48
|
+
c[:lazy_instrumentation] && c[:lazy_instrumentation].push("#{type.name}.#{field.name}: #{o.value}")
|
49
|
+
result
|
50
|
+
}
|
51
|
+
}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.build(execution_strategy)
|
56
|
+
lazy_push_type = GraphQL::ObjectType.define do
|
57
|
+
name "LazyPush"
|
58
|
+
field :value, !types.Int
|
59
|
+
field :push, !lazy_push_type do
|
60
|
+
argument :value, types.Int
|
61
|
+
resolve ->(o, a, c) {
|
62
|
+
LazyPush.new(c, a[:value])
|
63
|
+
}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
query_type = GraphQL::ObjectType.define do
|
68
|
+
name "Query"
|
69
|
+
field :push, !lazy_push_type do
|
70
|
+
argument :value, types.Int
|
71
|
+
resolve ->(o, a, c) {
|
72
|
+
LazyPush.new(c, a[:value])
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
connection :pushes, lazy_push_type.connection_type do
|
77
|
+
argument :values, types[types.Int]
|
78
|
+
resolve ->(o, a, c) {
|
79
|
+
LazyPushCollection.new(c, a[:values])
|
80
|
+
}
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
GraphQL::Schema.define do
|
85
|
+
query(query_type)
|
86
|
+
mutation(query_type)
|
87
|
+
query_execution_strategy(execution_strategy)
|
88
|
+
mutation_execution_strategy(execution_strategy)
|
89
|
+
lazy_resolve(LazyPush, :push)
|
90
|
+
lazy_resolve(LazyPushCollection, :push)
|
91
|
+
instrument(:field, LazyInstrumentation)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|