graphql 1.4.5 → 1.5.3
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/enum_generator.rb +33 -0
- data/lib/generators/graphql/function_generator.rb +15 -0
- data/lib/generators/graphql/install_generator.rb +118 -0
- data/lib/generators/graphql/interface_generator.rb +27 -0
- data/lib/generators/graphql/loader_generator.rb +17 -0
- data/lib/generators/graphql/mutation_generator.rb +19 -0
- data/lib/generators/graphql/object_generator.rb +34 -0
- data/lib/generators/graphql/templates/enum.erb +4 -0
- data/lib/generators/graphql/templates/function.erb +17 -0
- data/lib/generators/graphql/templates/graphql_controller.erb +32 -0
- data/lib/generators/graphql/templates/interface.erb +4 -0
- data/lib/generators/graphql/templates/loader.erb +15 -0
- data/lib/generators/graphql/templates/mutation.erb +12 -0
- data/lib/generators/graphql/templates/object.erb +5 -0
- data/lib/generators/graphql/templates/query_type.erb +15 -0
- data/lib/generators/graphql/templates/schema.erb +34 -0
- data/lib/generators/graphql/templates/union.erb +4 -0
- data/lib/generators/graphql/type_generator.rb +78 -0
- data/lib/generators/graphql/union_generator.rb +33 -0
- data/lib/graphql.rb +10 -0
- data/lib/graphql/analysis/analyze_query.rb +1 -1
- data/lib/graphql/analysis/query_complexity.rb +6 -50
- data/lib/graphql/analysis/query_depth.rb +1 -1
- data/lib/graphql/argument.rb +21 -0
- data/lib/graphql/compatibility/execution_specification/counter_schema.rb +3 -3
- data/lib/graphql/define.rb +1 -0
- data/lib/graphql/define/assign_argument.rb +3 -19
- data/lib/graphql/define/assign_mutation_function.rb +34 -0
- data/lib/graphql/define/assign_object_field.rb +26 -14
- data/lib/graphql/define/defined_object_proxy.rb +21 -0
- data/lib/graphql/define/instance_definable.rb +61 -11
- data/lib/graphql/directive.rb +6 -1
- data/lib/graphql/execution/directive_checks.rb +1 -0
- data/lib/graphql/execution/execute.rb +14 -9
- data/lib/graphql/execution/field_result.rb +1 -0
- data/lib/graphql/execution/lazy.rb +8 -17
- data/lib/graphql/execution/lazy/lazy_method_map.rb +2 -0
- data/lib/graphql/execution/lazy/resolve.rb +1 -0
- data/lib/graphql/execution/selection_result.rb +1 -0
- data/lib/graphql/execution/typecast.rb +39 -26
- data/lib/graphql/field.rb +15 -3
- data/lib/graphql/field/resolve.rb +3 -3
- data/lib/graphql/function.rb +134 -0
- data/lib/graphql/id_type.rb +1 -1
- data/lib/graphql/input_object_type.rb +1 -1
- data/lib/graphql/internal_representation.rb +1 -1
- data/lib/graphql/internal_representation/node.rb +35 -107
- data/lib/graphql/internal_representation/rewrite.rb +189 -183
- data/lib/graphql/internal_representation/visit.rb +38 -0
- data/lib/graphql/introspection/input_value_type.rb +10 -1
- data/lib/graphql/introspection/schema_type.rb +1 -1
- data/lib/graphql/language/lexer.rb +6 -3
- data/lib/graphql/language/lexer.rl +6 -3
- data/lib/graphql/object_type.rb +53 -13
- data/lib/graphql/query.rb +30 -14
- data/lib/graphql/query/arguments.rb +2 -0
- data/lib/graphql/query/context.rb +2 -2
- data/lib/graphql/query/literal_input.rb +9 -0
- data/lib/graphql/query/serial_execution/field_resolution.rb +2 -2
- data/lib/graphql/query/serial_execution/selection_resolution.rb +1 -1
- data/lib/graphql/relay.rb +1 -0
- data/lib/graphql/relay/array_connection.rb +1 -1
- data/lib/graphql/relay/base_connection.rb +34 -15
- data/lib/graphql/relay/connection_resolve.rb +7 -2
- data/lib/graphql/relay/mutation.rb +45 -4
- data/lib/graphql/relay/node.rb +18 -6
- data/lib/graphql/relay/range_add.rb +45 -0
- data/lib/graphql/relay/relation_connection.rb +17 -2
- data/lib/graphql/runtime_type_error.rb +1 -0
- data/lib/graphql/schema.rb +40 -5
- data/lib/graphql/schema/base_64_encoder.rb +1 -0
- data/lib/graphql/schema/build_from_definition.rb +56 -21
- data/lib/graphql/schema/default_parse_error.rb +10 -0
- data/lib/graphql/schema/loader.rb +8 -1
- data/lib/graphql/schema/null_mask.rb +1 -0
- data/lib/graphql/schema/validation.rb +35 -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 +7 -4
- data/lib/graphql/static_validation/definition_dependencies.rb +183 -0
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +28 -96
- data/lib/graphql/static_validation/rules/fragment_names_are_unique.rb +23 -0
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +8 -5
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +6 -31
- data/lib/graphql/static_validation/rules/fragments_are_used.rb +11 -41
- data/lib/graphql/static_validation/rules/operation_names_are_valid.rb +2 -2
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +19 -7
- data/lib/graphql/static_validation/validation_context.rb +22 -1
- data/lib/graphql/static_validation/validator.rb +4 -1
- data/lib/graphql/string_type.rb +5 -1
- data/lib/graphql/version.rb +1 -1
- data/readme.md +12 -3
- data/spec/generators/graphql/enum_generator_spec.rb +29 -0
- data/spec/generators/graphql/function_generator_spec.rb +33 -0
- data/spec/generators/graphql/install_generator_spec.rb +185 -0
- data/spec/generators/graphql/interface_generator_spec.rb +32 -0
- data/spec/generators/graphql/loader_generator_spec.rb +31 -0
- data/spec/generators/graphql/mutation_generator_spec.rb +28 -0
- data/spec/generators/graphql/object_generator_spec.rb +42 -0
- data/spec/generators/graphql/union_generator_spec.rb +50 -0
- data/spec/graphql/analysis/query_complexity_spec.rb +2 -1
- data/spec/graphql/define/instance_definable_spec.rb +38 -0
- data/spec/graphql/directive/skip_directive_spec.rb +1 -0
- data/spec/graphql/directive_spec.rb +18 -0
- data/spec/graphql/execution/typecast_spec.rb +41 -46
- data/spec/graphql/field_spec.rb +1 -1
- data/spec/graphql/function_spec.rb +128 -0
- data/spec/graphql/internal_representation/rewrite_spec.rb +166 -129
- data/spec/graphql/introspection/type_type_spec.rb +1 -1
- data/spec/graphql/language/lexer_spec.rb +6 -0
- data/spec/graphql/object_type_spec.rb +73 -2
- data/spec/graphql/query/arguments_spec.rb +28 -0
- data/spec/graphql/query/variables_spec.rb +7 -1
- data/spec/graphql/query_spec.rb +30 -0
- data/spec/graphql/relay/base_connection_spec.rb +26 -8
- data/spec/graphql/relay/connection_resolve_spec.rb +45 -0
- data/spec/graphql/relay/connection_type_spec.rb +21 -0
- data/spec/graphql/relay/node_spec.rb +30 -2
- data/spec/graphql/relay/range_add_spec.rb +113 -0
- data/spec/graphql/schema/build_from_definition_spec.rb +114 -0
- data/spec/graphql/schema/loader_spec.rb +1 -0
- data/spec/graphql/schema/printer_spec.rb +2 -2
- data/spec/graphql/schema/validation_spec.rb +80 -11
- data/spec/graphql/schema/warden_spec.rb +10 -10
- data/spec/graphql/schema_spec.rb +18 -1
- data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +16 -0
- data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +50 -3
- data/spec/graphql/static_validation/rules/fragment_names_are_unique_spec.rb +27 -0
- data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +57 -0
- data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +1 -1
- data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +14 -0
- data/spec/graphql/string_type_spec.rb +7 -0
- data/spec/spec_helper.rb +3 -3
- data/spec/support/base_generator_test.rb +7 -0
- data/spec/support/dummy/schema.rb +32 -30
- data/spec/support/star_wars/schema.rb +81 -23
- metadata +98 -20
- data/lib/graphql/internal_representation/selection.rb +0 -85
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module InternalRepresentation
|
4
|
+
# Traverse a re-written query tree, calling handlers for each node
|
5
|
+
module Visit
|
6
|
+
module_function
|
7
|
+
def visit_each_node(operations, handlers)
|
8
|
+
# Post-validation: make some assertions about the rewritten query tree
|
9
|
+
operations.each do |op_name, op_node|
|
10
|
+
# Yield each node to listeners which were attached by validators
|
11
|
+
op_node.typed_children.each do |obj_type, children|
|
12
|
+
children.each do |name, op_child_node|
|
13
|
+
each_node(op_child_node) do |node|
|
14
|
+
for h in handlers
|
15
|
+
h.call(node)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Traverse a node in a rewritten query tree,
|
24
|
+
# visiting the node itself and each of its typed children.
|
25
|
+
def each_node(node)
|
26
|
+
yield(node)
|
27
|
+
if node.typed_children.any?
|
28
|
+
visit_block = Proc.new
|
29
|
+
node.typed_children.each do |obj_type, children|
|
30
|
+
children.each do |name, node|
|
31
|
+
each_node(node, &visit_block)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -11,7 +11,16 @@ GraphQL::Introspection::InputValueType = GraphQL::ObjectType.define do
|
|
11
11
|
resolve ->(obj, args, ctx) {
|
12
12
|
if obj.default_value?
|
13
13
|
value = obj.default_value
|
14
|
-
value.nil?
|
14
|
+
if value.nil?
|
15
|
+
'null'
|
16
|
+
else
|
17
|
+
coerced_default_value = obj.type.coerce_result(value)
|
18
|
+
if obj.type.unwrap.is_a?(GraphQL::EnumType)
|
19
|
+
coerced_default_value
|
20
|
+
else
|
21
|
+
GraphQL::Language.serialize(coerced_default_value)
|
22
|
+
end
|
23
|
+
end
|
15
24
|
else
|
16
25
|
nil
|
17
26
|
end
|
@@ -6,7 +6,7 @@ GraphQL::Introspection::SchemaType = GraphQL::ObjectType.define do
|
|
6
6
|
"query, mutation, and subscription operations."
|
7
7
|
|
8
8
|
field :types, !types[!GraphQL::Introspection::TypeType], "A list of all types supported by this server." do
|
9
|
-
resolve ->
|
9
|
+
resolve ->(obj, arg, ctx) { ctx.warden.types }
|
10
10
|
end
|
11
11
|
|
12
12
|
field :queryType, !GraphQL::Introspection::TypeType, "The type that query operations will be rooted at." do
|
@@ -990,7 +990,7 @@ end
|
|
990
990
|
def self.record_comment(ts, te, meta)
|
991
991
|
token = GraphQL::Language::Token.new(
|
992
992
|
name: :COMMENT,
|
993
|
-
value: meta[:data][ts...te].pack(
|
993
|
+
value: meta[:data][ts...te].pack(PACK_DIRECTIVE).force_encoding(UTF_8_ENCODING),
|
994
994
|
line: meta[:line],
|
995
995
|
col: meta[:col],
|
996
996
|
prev_token: meta[:previous_token],
|
@@ -1004,7 +1004,7 @@ end
|
|
1004
1004
|
def self.emit(token_name, ts, te, meta)
|
1005
1005
|
meta[:tokens] << token = GraphQL::Language::Token.new(
|
1006
1006
|
name: token_name,
|
1007
|
-
value: meta[:data][ts...te].pack(
|
1007
|
+
value: meta[:data][ts...te].pack(PACK_DIRECTIVE).force_encoding(UTF_8_ENCODING),
|
1008
1008
|
line: meta[:line],
|
1009
1009
|
col: meta[:col],
|
1010
1010
|
prev_token: meta[:previous_token],
|
@@ -1031,8 +1031,11 @@ end
|
|
1031
1031
|
|
1032
1032
|
VALID_STRING = /\A(?:[^\\]|#{ESCAPES}|#{UTF_8})*\z/o
|
1033
1033
|
|
1034
|
+
PACK_DIRECTIVE = "c*"
|
1035
|
+
UTF_8_ENCODING = "UTF-8"
|
1036
|
+
|
1034
1037
|
def self.emit_string(ts, te, meta)
|
1035
|
-
value = meta[:data][ts...te].pack(
|
1038
|
+
value = meta[:data][ts...te].pack(PACK_DIRECTIVE).force_encoding(UTF_8_ENCODING)
|
1036
1039
|
if value !~ VALID_STRING
|
1037
1040
|
meta[:tokens] << token = GraphQL::Language::Token.new(
|
1038
1041
|
name: :BAD_UNICODE_ESCAPE,
|
@@ -145,7 +145,7 @@ module GraphQL
|
|
145
145
|
def self.record_comment(ts, te, meta)
|
146
146
|
token = GraphQL::Language::Token.new(
|
147
147
|
name: :COMMENT,
|
148
|
-
value: meta[:data][ts...te].pack(
|
148
|
+
value: meta[:data][ts...te].pack(PACK_DIRECTIVE).force_encoding(UTF_8_ENCODING),
|
149
149
|
line: meta[:line],
|
150
150
|
col: meta[:col],
|
151
151
|
prev_token: meta[:previous_token],
|
@@ -159,7 +159,7 @@ module GraphQL
|
|
159
159
|
def self.emit(token_name, ts, te, meta)
|
160
160
|
meta[:tokens] << token = GraphQL::Language::Token.new(
|
161
161
|
name: token_name,
|
162
|
-
value: meta[:data][ts...te].pack(
|
162
|
+
value: meta[:data][ts...te].pack(PACK_DIRECTIVE).force_encoding(UTF_8_ENCODING),
|
163
163
|
line: meta[:line],
|
164
164
|
col: meta[:col],
|
165
165
|
prev_token: meta[:previous_token],
|
@@ -186,8 +186,11 @@ module GraphQL
|
|
186
186
|
|
187
187
|
VALID_STRING = /\A(?:[^\\]|#{ESCAPES}|#{UTF_8})*\z/o
|
188
188
|
|
189
|
+
PACK_DIRECTIVE = "c*"
|
190
|
+
UTF_8_ENCODING = "UTF-8"
|
191
|
+
|
189
192
|
def self.emit_string(ts, te, meta)
|
190
|
-
value = meta[:data][ts...te].pack(
|
193
|
+
value = meta[:data][ts...te].pack(PACK_DIRECTIVE).force_encoding(UTF_8_ENCODING)
|
191
194
|
if value !~ VALID_STRING
|
192
195
|
meta[:tokens] << token = GraphQL::Language::Token.new(
|
193
196
|
name: :BAD_UNICODE_ESCAPE,
|
data/lib/graphql/object_type.rb
CHANGED
@@ -23,6 +23,7 @@ module GraphQL
|
|
23
23
|
#
|
24
24
|
class ObjectType < GraphQL::BaseType
|
25
25
|
accepts_definitions :interfaces, :fields, :mutation, field: GraphQL::Define::AssignObjectField
|
26
|
+
accepts_definitions implements: ->(type, *interfaces, inherit: false) { type.implements(interfaces, inherit: inherit) }
|
26
27
|
|
27
28
|
attr_accessor :fields, :mutation
|
28
29
|
ensure_defined(:fields, :mutation, :interfaces)
|
@@ -33,34 +34,39 @@ module GraphQL
|
|
33
34
|
# @!attribute mutation
|
34
35
|
# @return [GraphQL::Relay::Mutation, nil] The mutation this field was derived from, if it was derived from a mutation
|
35
36
|
|
36
|
-
|
37
37
|
def initialize
|
38
38
|
super
|
39
39
|
@fields = {}
|
40
|
+
@interface_fields = {}
|
40
41
|
@dirty_interfaces = []
|
42
|
+
@dirty_inherited_interfaces = []
|
41
43
|
end
|
42
44
|
|
43
45
|
def initialize_copy(other)
|
44
46
|
super
|
45
47
|
@clean_interfaces = nil
|
48
|
+
@clean_inherited_interfaces = nil
|
46
49
|
@dirty_interfaces = other.dirty_interfaces.dup
|
50
|
+
@dirty_inherited_interfaces = other.dirty_inherited_interfaces.dup
|
47
51
|
@fields = other.fields.dup
|
48
52
|
end
|
49
53
|
|
54
|
+
# This method declares interfaces for this type AND inherits any field definitions
|
50
55
|
# @param new_interfaces [Array<GraphQL::Interface>] interfaces that this type implements
|
56
|
+
# @deprecated Use `implements` instead of `interfaces`.
|
51
57
|
def interfaces=(new_interfaces)
|
52
58
|
@clean_interfaces = nil
|
53
|
-
@
|
59
|
+
@clean_inherited_interfaces = nil
|
60
|
+
@clean_inherited_fields = nil
|
61
|
+
|
62
|
+
@dirty_inherited_interfaces = []
|
63
|
+
@dirty_inherited_fields = {}
|
64
|
+
implements(new_interfaces, inherit: true)
|
54
65
|
end
|
55
66
|
|
56
67
|
def interfaces
|
57
|
-
|
58
|
-
|
59
|
-
@dirty_interfaces.map { |i_type| GraphQL::BaseType.resolve_related_type(i_type) }
|
60
|
-
else
|
61
|
-
@dirty_interfaces
|
62
|
-
end
|
63
|
-
end
|
68
|
+
load_interfaces
|
69
|
+
@clean_interfaces
|
64
70
|
end
|
65
71
|
|
66
72
|
def kind
|
@@ -77,16 +83,50 @@ module GraphQL
|
|
77
83
|
interface_fields.merge(self.fields).values
|
78
84
|
end
|
79
85
|
|
86
|
+
# Declare that this object implements this interface.
|
87
|
+
# This declaration will be validated when the schema is defined.
|
88
|
+
# @param interfaces [Array<GraphQL::Interface>] add a new interface that this type implements
|
89
|
+
# @param inherits [Boolean] If true, copy the interfaces' field definitions to this type
|
90
|
+
def implements(interfaces, inherit: false)
|
91
|
+
if !interfaces.is_a?(Array)
|
92
|
+
raise ArgumentError, "`implements(interfaces)` must be an array, not #{interfaces.class} (#{interfaces})"
|
93
|
+
end
|
94
|
+
|
95
|
+
@clean_interfaces = nil
|
96
|
+
@clean_inherited_fields = nil
|
97
|
+
dirty_ifaces = inherit ? @dirty_inherited_interfaces : @dirty_interfaces
|
98
|
+
dirty_ifaces.concat(interfaces)
|
99
|
+
end
|
100
|
+
|
80
101
|
protected
|
81
102
|
|
82
|
-
attr_reader :dirty_interfaces
|
103
|
+
attr_reader :dirty_interfaces, :dirty_inherited_interfaces
|
83
104
|
|
84
105
|
private
|
85
106
|
|
86
|
-
|
107
|
+
def normalize_interfaces(ifaces)
|
108
|
+
ifaces.map { |i_type| GraphQL::BaseType.resolve_related_type(i_type) }
|
109
|
+
end
|
110
|
+
|
87
111
|
def interface_fields
|
88
|
-
|
89
|
-
|
112
|
+
load_interfaces
|
113
|
+
@clean_inherited_fields
|
114
|
+
end
|
115
|
+
|
116
|
+
def load_interfaces
|
117
|
+
@clean_interfaces ||= begin
|
118
|
+
ensure_defined
|
119
|
+
clean_ifaces = normalize_interfaces(@dirty_interfaces)
|
120
|
+
clean_inherited_ifaces = normalize_interfaces(@dirty_inherited_interfaces)
|
121
|
+
inherited_fields = {}
|
122
|
+
clean_inherited_ifaces.each do |iface|
|
123
|
+
# This will be found later in schema validation:
|
124
|
+
if iface.is_a?(GraphQL::InterfaceType)
|
125
|
+
inherited_fields.merge!(iface.fields)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
@clean_inherited_fields = inherited_fields
|
129
|
+
clean_inherited_ifaces + clean_ifaces
|
90
130
|
end
|
91
131
|
end
|
92
132
|
end
|
data/lib/graphql/query.rb
CHANGED
@@ -35,7 +35,8 @@ module GraphQL
|
|
35
35
|
# @param root_value [Object] the object used to resolve fields on the root type
|
36
36
|
# @param max_depth [Numeric] the maximum number of nested selections allowed for this query (falls back to schema-level value)
|
37
37
|
# @param max_complexity [Numeric] the maximum field complexity for this query (falls back to schema-level value)
|
38
|
-
# @param except [<#call(schema_member)>] If provided, objects will be hidden from the schema when `.call(schema_member)` returns truthy
|
38
|
+
# @param except [<#call(schema_member, context)>] If provided, objects will be hidden from the schema when `.call(schema_member, context)` returns truthy
|
39
|
+
# @param only [<#call(schema_member, context)>] If provided, objects will be hidden from the schema when `.call(schema_member, context)` returns false
|
39
40
|
def initialize(schema, query_string = nil, document: nil, context: nil, variables: {}, validate: true, operation_name: nil, root_value: nil, max_depth: nil, max_complexity: nil, except: nil, only: nil)
|
40
41
|
fail ArgumentError, "a query string or document is required" unless query_string || document
|
41
42
|
|
@@ -62,8 +63,15 @@ module GraphQL
|
|
62
63
|
@provided_variables = variables
|
63
64
|
end
|
64
65
|
@query_string = query_string
|
65
|
-
@
|
66
|
-
@document
|
66
|
+
@parse_error = nil
|
67
|
+
@document = document || begin
|
68
|
+
GraphQL.parse(query_string)
|
69
|
+
rescue GraphQL::ParseError => err
|
70
|
+
@parse_error = err
|
71
|
+
@schema.parse_error(err, @context)
|
72
|
+
nil
|
73
|
+
end
|
74
|
+
@document && @document.definitions.each do |part|
|
67
75
|
if part.is_a?(GraphQL::Language::Nodes::FragmentDefinition)
|
68
76
|
@fragments[part.name] = part
|
69
77
|
elsif part.is_a?(GraphQL::Language::Nodes::OperationDefinition)
|
@@ -109,7 +117,7 @@ module GraphQL
|
|
109
117
|
begin
|
110
118
|
instrumenters.each { |i| i.before_query(self) }
|
111
119
|
@result = if !valid?
|
112
|
-
all_errors = validation_errors + analysis_errors
|
120
|
+
all_errors = validation_errors + analysis_errors + context.errors
|
113
121
|
if all_errors.any?
|
114
122
|
{ "errors" => all_errors.map(&:to_h) }
|
115
123
|
else
|
@@ -156,10 +164,7 @@ module GraphQL
|
|
156
164
|
end
|
157
165
|
|
158
166
|
def irep_selection
|
159
|
-
@selection ||=
|
160
|
-
irep_root = internal_representation[selected_operation.name]
|
161
|
-
GraphQL::InternalRepresentation::Selection.new(query: self, nodes: [irep_root])
|
162
|
-
end
|
167
|
+
@selection ||= internal_representation[selected_operation.name]
|
163
168
|
end
|
164
169
|
|
165
170
|
|
@@ -181,11 +186,22 @@ module GraphQL
|
|
181
186
|
# @return [GraphQL::Query::Arguments] Arguments for this node, merging default values, literal values and query variables
|
182
187
|
def arguments_for(irep_node, definition)
|
183
188
|
@arguments_cache[irep_node][definition] ||= begin
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
+
ast_node = case irep_node
|
190
|
+
when GraphQL::Language::Nodes::AbstractNode
|
191
|
+
irep_node
|
192
|
+
else
|
193
|
+
irep_node.ast_node
|
194
|
+
end
|
195
|
+
ast_arguments = ast_node.arguments
|
196
|
+
if ast_arguments.none?
|
197
|
+
definition.default_arguments
|
198
|
+
else
|
199
|
+
GraphQL::Query::LiteralInput.from_arguments(
|
200
|
+
ast_arguments,
|
201
|
+
definition.arguments,
|
202
|
+
self.variables
|
203
|
+
)
|
204
|
+
end
|
189
205
|
end
|
190
206
|
end
|
191
207
|
|
@@ -195,7 +211,7 @@ module GraphQL
|
|
195
211
|
def valid?
|
196
212
|
@was_validated ||= begin
|
197
213
|
@was_validated = true
|
198
|
-
@valid = document_valid? && query_valid? && variables.errors.none?
|
214
|
+
@valid = @parse_error.nil? && document_valid? && query_valid? && variables.errors.none?
|
199
215
|
true
|
200
216
|
end
|
201
217
|
|
@@ -88,12 +88,12 @@ module GraphQL
|
|
88
88
|
|
89
89
|
# @return [GraphQL::Language::Nodes::Field] The AST node for the currently-executing field
|
90
90
|
def ast_node
|
91
|
-
selection.
|
91
|
+
@selection.ast_node
|
92
92
|
end
|
93
93
|
|
94
94
|
# @return [GraphQL::InternalRepresentation::Node]
|
95
95
|
def irep_node
|
96
|
-
selection
|
96
|
+
@selection
|
97
97
|
end
|
98
98
|
|
99
99
|
# Add error to current field resolution.
|
@@ -29,7 +29,16 @@ module GraphQL
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
+
def self.defaults_for(argument_defns)
|
33
|
+
if argument_defns.none? { |name, arg| arg.default_value? }
|
34
|
+
GraphQL::Query::Arguments::NO_ARGS
|
35
|
+
else
|
36
|
+
from_arguments([], argument_defns, nil)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
32
40
|
def self.from_arguments(ast_arguments, argument_defns, variables)
|
41
|
+
|
33
42
|
values_hash = {}
|
34
43
|
indexed_arguments = ast_arguments.each_with_object({}) { |a, memo| memo[a.name] = a }
|
35
44
|
|
@@ -6,12 +6,12 @@ module GraphQL
|
|
6
6
|
attr_reader :irep_node, :parent_type, :target, :field, :arguments, :query
|
7
7
|
|
8
8
|
def initialize(selection, parent_type, target, query_ctx)
|
9
|
-
@irep_node = selection
|
9
|
+
@irep_node = selection
|
10
10
|
@selection = selection
|
11
11
|
@parent_type = parent_type
|
12
12
|
@target = target
|
13
13
|
@query = query_ctx.query
|
14
|
-
@field =
|
14
|
+
@field = irep_node.definition
|
15
15
|
@field_ctx = query_ctx.spawn(
|
16
16
|
key: irep_node.name,
|
17
17
|
selection: selection,
|
@@ -6,7 +6,7 @@ module GraphQL
|
|
6
6
|
def self.resolve(target, current_type, selection, query_ctx)
|
7
7
|
selection_result = {}
|
8
8
|
|
9
|
-
selection.
|
9
|
+
selection.typed_children[current_type].each do |name, subselection|
|
10
10
|
selection_result.merge!(query_ctx.execution_strategy.field_resolution.new(
|
11
11
|
subselection,
|
12
12
|
current_type,
|
data/lib/graphql/relay.rb
CHANGED
@@ -6,6 +6,7 @@ require 'graphql/relay/edge'
|
|
6
6
|
require 'graphql/relay/edge_type'
|
7
7
|
require 'graphql/relay/base_connection'
|
8
8
|
require 'graphql/relay/array_connection'
|
9
|
+
require 'graphql/relay/range_add'
|
9
10
|
require 'graphql/relay/relation_connection'
|
10
11
|
require 'graphql/relay/global_id_resolve'
|
11
12
|
require 'graphql/relay/mutation'
|
@@ -74,21 +74,28 @@ module GraphQL
|
|
74
74
|
@encoder.decode(data, nonce: true)
|
75
75
|
end
|
76
76
|
|
77
|
-
#
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
#
|
84
|
-
#
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
77
|
+
# The value passed as `first:`, if there was one. Negative numbers become `0`.
|
78
|
+
# @return [Integer, nil]
|
79
|
+
def first
|
80
|
+
@first ||= get_limited_arg(:first)
|
81
|
+
end
|
82
|
+
|
83
|
+
# The value passed as `after:`, if there was one
|
84
|
+
# @return [String, nil]
|
85
|
+
def after
|
86
|
+
arguments[:after]
|
87
|
+
end
|
88
|
+
|
89
|
+
# The value passed as `last:`, if there was one. Negative numbers become `0`.
|
90
|
+
# @return [Integer, nil]
|
91
|
+
def last
|
92
|
+
@last ||= get_limited_arg(:last)
|
93
|
+
end
|
94
|
+
|
95
|
+
# The value passed as `before:`, if there was one
|
96
|
+
# @return [String, nil]
|
97
|
+
def before
|
98
|
+
arguments[:before]
|
92
99
|
end
|
93
100
|
|
94
101
|
# These are the nodes to render for this connection,
|
@@ -137,6 +144,18 @@ module GraphQL
|
|
137
144
|
|
138
145
|
private
|
139
146
|
|
147
|
+
# Return a sanitized `arguments[arg_name]` (don't allow negatives)
|
148
|
+
def get_limited_arg(arg_name)
|
149
|
+
arg_value = arguments[arg_name]
|
150
|
+
if arg_value.nil?
|
151
|
+
arg_value
|
152
|
+
elsif arg_value < 0
|
153
|
+
0
|
154
|
+
else
|
155
|
+
arg_value
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
140
159
|
def paged_nodes
|
141
160
|
raise NotImplementedError, "must return nodes for this connection after paging"
|
142
161
|
end
|