graphql 1.11.4 → 1.11.5
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/templates/union.erb +1 -1
- data/lib/graphql.rb +16 -0
- data/lib/graphql/argument.rb +3 -3
- data/lib/graphql/backtrace/tracer.rb +2 -1
- data/lib/graphql/execution/interpreter.rb +10 -0
- data/lib/graphql/execution/interpreter/arguments.rb +1 -1
- data/lib/graphql/execution/interpreter/runtime.rb +32 -18
- data/lib/graphql/introspection.rb +96 -0
- data/lib/graphql/introspection/field_type.rb +7 -3
- data/lib/graphql/introspection/input_value_type.rb +6 -0
- data/lib/graphql/introspection/introspection_query.rb +6 -92
- data/lib/graphql/introspection/type_type.rb +7 -3
- data/lib/graphql/language/block_string.rb +24 -5
- data/lib/graphql/language/lexer.rb +7 -3
- data/lib/graphql/language/lexer.rl +7 -3
- data/lib/graphql/language/nodes.rb +1 -1
- data/lib/graphql/language/parser.rb +107 -103
- data/lib/graphql/language/parser.y +4 -0
- data/lib/graphql/language/sanitized_printer.rb +59 -26
- data/lib/graphql/name_validator.rb +6 -7
- data/lib/graphql/pagination/connections.rb +2 -0
- data/lib/graphql/query.rb +2 -2
- data/lib/graphql/query/context.rb +10 -2
- data/lib/graphql/schema.rb +30 -16
- data/lib/graphql/schema/argument.rb +56 -5
- data/lib/graphql/schema/build_from_definition.rb +60 -35
- data/lib/graphql/schema/directive/deprecated.rb +1 -1
- data/lib/graphql/schema/field.rb +10 -4
- data/lib/graphql/schema/input_object.rb +5 -3
- data/lib/graphql/schema/interface.rb +1 -1
- data/lib/graphql/schema/late_bound_type.rb +2 -2
- data/lib/graphql/schema/loader.rb +1 -0
- data/lib/graphql/schema/member/build_type.rb +14 -4
- data/lib/graphql/schema/member/has_arguments.rb +3 -1
- data/lib/graphql/schema/member/type_system_helpers.rb +2 -2
- data/lib/graphql/schema/relay_classic_mutation.rb +3 -1
- data/lib/graphql/schema/timeout.rb +29 -15
- data/lib/graphql/schema/validation.rb +8 -0
- data/lib/graphql/static_validation/validator.rb +7 -4
- data/lib/graphql/subscriptions.rb +1 -3
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +21 -7
- data/lib/graphql/version.rb +1 -1
- metadata +2 -2
@@ -466,6 +466,10 @@ def self.parse(query_string, filename: nil, tracer: GraphQL::Tracing::NullTracer
|
|
466
466
|
self.new(query_string, filename: filename, tracer: tracer).parse_document
|
467
467
|
end
|
468
468
|
|
469
|
+
def self.parse_file(filename, tracer: GraphQL::Tracing::NullTracer)
|
470
|
+
self.parse(File.read(filename), filename: filename, tracer: tracer)
|
471
|
+
end
|
472
|
+
|
469
473
|
private
|
470
474
|
|
471
475
|
def next_token
|
@@ -19,11 +19,12 @@ module GraphQL
|
|
19
19
|
|
20
20
|
REDACTED = "\"<REDACTED>\""
|
21
21
|
|
22
|
-
def initialize(query)
|
22
|
+
def initialize(query, inline_variables: true)
|
23
23
|
@query = query
|
24
24
|
@current_type = nil
|
25
25
|
@current_field = nil
|
26
26
|
@current_input_type = nil
|
27
|
+
@inline_variables = inline_variables
|
27
28
|
end
|
28
29
|
|
29
30
|
# @return [String, nil] A scrubbed query string, if the query was valid.
|
@@ -36,15 +37,14 @@ module GraphQL
|
|
36
37
|
end
|
37
38
|
|
38
39
|
def print_node(node, indent: "")
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
super
|
40
|
+
case node
|
41
|
+
when FalseClass, Float, Integer, String, TrueClass
|
42
|
+
if @current_argument && redact_argument_value?(@current_argument, node)
|
43
|
+
redacted_argument_value(@current_argument)
|
44
44
|
else
|
45
|
-
|
45
|
+
super
|
46
46
|
end
|
47
|
-
|
47
|
+
when Array
|
48
48
|
old_input_type = @current_input_type
|
49
49
|
if @current_input_type && @current_input_type.list?
|
50
50
|
@current_input_type = @current_input_type.of_type
|
@@ -59,28 +59,57 @@ module GraphQL
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
+
# Indicates whether or not to redact non-null values for the given argument. Defaults to redacting all strings
|
63
|
+
# arguments but this can be customized by subclasses.
|
64
|
+
def redact_argument_value?(argument, value)
|
65
|
+
# Default to redacting any strings or custom scalars encoded as strings
|
66
|
+
type = argument.type.unwrap
|
67
|
+
value.is_a?(String) && type.kind.scalar? && (type.graphql_name == "String" || !type.default_scalar?)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Returns the value to use for redacted versions of the given argument. Defaults to the
|
71
|
+
# string "<REDACTED>".
|
72
|
+
def redacted_argument_value(argument)
|
73
|
+
REDACTED
|
74
|
+
end
|
75
|
+
|
62
76
|
def print_argument(argument)
|
77
|
+
# We won't have type information if we're recursing into a custom scalar
|
78
|
+
return super if @current_input_type && @current_input_type.kind.scalar?
|
79
|
+
|
63
80
|
arg_owner = @current_input_type || @current_directive || @current_field
|
64
|
-
|
81
|
+
old_current_argument = @current_argument
|
82
|
+
@current_argument = arg_owner.arguments[argument.name]
|
65
83
|
|
66
84
|
old_input_type = @current_input_type
|
67
|
-
@current_input_type =
|
68
|
-
|
85
|
+
@current_input_type = @current_argument.type.non_null? ? @current_argument.type.of_type : @current_argument.type
|
86
|
+
|
87
|
+
argument_value = if coerce_argument_value_to_list?(@current_input_type, argument.value)
|
88
|
+
[argument.value]
|
89
|
+
else
|
90
|
+
argument.value
|
91
|
+
end
|
92
|
+
res = "#{argument.name}: #{print_node(argument_value)}".dup
|
93
|
+
|
69
94
|
@current_input_type = old_input_type
|
95
|
+
@current_argument = old_current_argument
|
70
96
|
res
|
71
97
|
end
|
72
98
|
|
73
|
-
def
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
res
|
99
|
+
def coerce_argument_value_to_list?(type, value)
|
100
|
+
type.list? &&
|
101
|
+
!value.is_a?(Array) &&
|
102
|
+
!value.nil? &&
|
103
|
+
!value.is_a?(GraphQL::Language::Nodes::VariableIdentifier)
|
79
104
|
end
|
80
105
|
|
81
106
|
def print_variable_identifier(variable_id)
|
82
|
-
|
83
|
-
|
107
|
+
if @inline_variables
|
108
|
+
variable_value = query.variables[variable_id.name]
|
109
|
+
print_node(value_to_ast(variable_value, @current_input_type))
|
110
|
+
else
|
111
|
+
super
|
112
|
+
end
|
84
113
|
end
|
85
114
|
|
86
115
|
def print_field(field, indent: "")
|
@@ -132,10 +161,14 @@ module GraphQL
|
|
132
161
|
old_type = @current_type
|
133
162
|
@current_type = query.schema.public_send(operation_definition.operation_type)
|
134
163
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
164
|
+
if @inline_variables
|
165
|
+
out = "#{indent}#{operation_definition.operation_type}".dup
|
166
|
+
out << " #{operation_definition.name}" if operation_definition.name
|
167
|
+
out << print_directives(operation_definition.directives)
|
168
|
+
out << print_selections(operation_definition.selections, indent: indent)
|
169
|
+
else
|
170
|
+
out = super
|
171
|
+
end
|
139
172
|
|
140
173
|
@current_type = old_type
|
141
174
|
out
|
@@ -171,10 +204,10 @@ module GraphQL
|
|
171
204
|
arguments: arguments
|
172
205
|
)
|
173
206
|
when "LIST"
|
174
|
-
if value.
|
175
|
-
value.
|
207
|
+
if value.is_a?(Array)
|
208
|
+
value.map { |v| value_to_ast(v, type.of_type) }
|
176
209
|
else
|
177
|
-
[value].
|
210
|
+
[value].map { |v| value_to_ast(v, type.of_type) }
|
178
211
|
end
|
179
212
|
when "ENUM"
|
180
213
|
GraphQL::Language::Nodes::Enum.new(name: value)
|
@@ -1,16 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module GraphQL
|
3
3
|
class NameValidator
|
4
|
-
|
5
|
-
|
6
|
-
def self.validate!(name)
|
7
|
-
raise GraphQL::InvalidNameError.new(name, VALID_NAME_REGEX) unless valid?(name)
|
4
|
+
if !String.method_defined?(:match?)
|
5
|
+
using GraphQL::StringMatchBackport
|
8
6
|
end
|
9
7
|
|
10
|
-
|
8
|
+
VALID_NAME_REGEX = /^[_a-zA-Z][_a-zA-Z0-9]*$/
|
11
9
|
|
12
|
-
def self.
|
13
|
-
name
|
10
|
+
def self.validate!(name)
|
11
|
+
name = name.is_a?(String) ? name : name.to_s
|
12
|
+
raise GraphQL::InvalidNameError.new(name, VALID_NAME_REGEX) unless name.match?(VALID_NAME_REGEX)
|
14
13
|
end
|
15
14
|
end
|
16
15
|
end
|
@@ -66,6 +66,8 @@ module GraphQL
|
|
66
66
|
# Used by the runtime to wrap values in connection wrappers.
|
67
67
|
# @api Private
|
68
68
|
def wrap(field, parent, items, arguments, context, wrappers: all_wrappers)
|
69
|
+
return items if GraphQL::Execution::Interpreter::RawValue === items
|
70
|
+
|
69
71
|
impl = nil
|
70
72
|
|
71
73
|
items.class.ancestors.each { |cls|
|
data/lib/graphql/query.rb
CHANGED
@@ -259,9 +259,9 @@ module GraphQL
|
|
259
259
|
# - Variables inlined to the query
|
260
260
|
# - Strings replaced with `<REDACTED>`
|
261
261
|
# @return [String, nil] Returns nil if the query is invalid.
|
262
|
-
def sanitized_query_string
|
262
|
+
def sanitized_query_string(inline_variables: true)
|
263
263
|
with_prepared_ast {
|
264
|
-
GraphQL::Language::SanitizedPrinter.new(self).sanitized_query_string
|
264
|
+
GraphQL::Language::SanitizedPrinter.new(self, inline_variables: inline_variables).sanitized_query_string
|
265
265
|
}
|
266
266
|
end
|
267
267
|
|
@@ -34,7 +34,7 @@ module GraphQL
|
|
34
34
|
# Remove this child from the result value
|
35
35
|
# (used for null propagation and skip)
|
36
36
|
# @api private
|
37
|
-
def
|
37
|
+
def delete_child(child_ctx)
|
38
38
|
@value.delete(child_ctx.key)
|
39
39
|
end
|
40
40
|
|
@@ -179,6 +179,14 @@ module GraphQL
|
|
179
179
|
@provided_values[key]
|
180
180
|
end
|
181
181
|
|
182
|
+
def delete(key)
|
183
|
+
if @scoped_context.key?(key)
|
184
|
+
@scoped_context.delete(key)
|
185
|
+
else
|
186
|
+
@provided_values.delete(key)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
182
190
|
UNSPECIFIED_FETCH_DEFAULT = Object.new
|
183
191
|
|
184
192
|
def fetch(key, default = UNSPECIFIED_FETCH_DEFAULT)
|
@@ -312,7 +320,7 @@ module GraphQL
|
|
312
320
|
end
|
313
321
|
when GraphQL::Execution::Execute::SKIP
|
314
322
|
@parent.skipped = true
|
315
|
-
@parent.
|
323
|
+
@parent.delete_child(self)
|
316
324
|
else
|
317
325
|
@value = new_value
|
318
326
|
end
|
data/lib/graphql/schema.rb
CHANGED
@@ -789,20 +789,25 @@ module GraphQL
|
|
789
789
|
# @param using [Hash] Plugins to attach to the created schema with `use(key, value)`
|
790
790
|
# @param interpreter [Boolean] If false, the legacy {Execution::Execute} runtime will be used
|
791
791
|
# @return [Class] the schema described by `document`
|
792
|
-
def self.from_definition(definition_or_path, default_resolve: nil, interpreter: true, parser:
|
792
|
+
def self.from_definition(definition_or_path, default_resolve: nil, interpreter: true, parser: GraphQL.default_parser, using: {})
|
793
793
|
# If the file ends in `.graphql`, treat it like a filepath
|
794
|
-
|
795
|
-
|
794
|
+
if definition_or_path.end_with?(".graphql")
|
795
|
+
GraphQL::Schema::BuildFromDefinition.from_definition_path(
|
796
|
+
definition_or_path,
|
797
|
+
default_resolve: default_resolve,
|
798
|
+
parser: parser,
|
799
|
+
using: using,
|
800
|
+
interpreter: interpreter,
|
801
|
+
)
|
796
802
|
else
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
)
|
803
|
+
GraphQL::Schema::BuildFromDefinition.from_definition(
|
804
|
+
definition_or_path,
|
805
|
+
default_resolve: default_resolve,
|
806
|
+
parser: parser,
|
807
|
+
using: using,
|
808
|
+
interpreter: interpreter,
|
809
|
+
)
|
810
|
+
end
|
806
811
|
end
|
807
812
|
|
808
813
|
# Error that is raised when [#Schema#from_definition] is passed an invalid schema definition string.
|
@@ -832,7 +837,7 @@ module GraphQL
|
|
832
837
|
# @param except [<#call(member, ctx)>]
|
833
838
|
# @return [Hash] GraphQL result
|
834
839
|
def as_json(only: nil, except: nil, context: {})
|
835
|
-
execute(Introspection
|
840
|
+
execute(Introspection.query(include_deprecated_args: true), only: only, except: except, context: context).to_h
|
836
841
|
end
|
837
842
|
|
838
843
|
# Returns the JSON response of {Introspection::INTROSPECTION_QUERY}.
|
@@ -880,7 +885,7 @@ module GraphQL
|
|
880
885
|
# @param except [<#call(member, ctx)>]
|
881
886
|
# @return [Hash] GraphQL result
|
882
887
|
def as_json(only: nil, except: nil, context: {})
|
883
|
-
execute(Introspection
|
888
|
+
execute(Introspection.query(include_deprecated_args: true), only: only, except: except, context: context).to_h
|
884
889
|
end
|
885
890
|
|
886
891
|
# Return the GraphQL IDL for the schema
|
@@ -1112,7 +1117,16 @@ module GraphQL
|
|
1112
1117
|
if type.kind.union?
|
1113
1118
|
type.possible_types(context: context)
|
1114
1119
|
else
|
1115
|
-
own_possible_types[type.graphql_name]
|
1120
|
+
stored_possible_types = own_possible_types[type.graphql_name]
|
1121
|
+
visible_possible_types = stored_possible_types.select do |possible_type|
|
1122
|
+
next true unless type.kind.interface?
|
1123
|
+
next true unless possible_type.kind.object?
|
1124
|
+
|
1125
|
+
# Use `.graphql_name` comparison to match legacy vs class-based types.
|
1126
|
+
# When we don't need to support legacy `.define` types, use `.include?(type)` instead.
|
1127
|
+
possible_type.interfaces(context).any? { |interface| interface.graphql_name == type.graphql_name }
|
1128
|
+
end if stored_possible_types
|
1129
|
+
visible_possible_types ||
|
1116
1130
|
introspection_system.possible_types[type.graphql_name] ||
|
1117
1131
|
(
|
1118
1132
|
superclass.respond_to?(:possible_types) ?
|
@@ -1664,7 +1678,7 @@ module GraphQL
|
|
1664
1678
|
end
|
1665
1679
|
|
1666
1680
|
def query_stack_error(query, err)
|
1667
|
-
query.
|
1681
|
+
query.context.errors.push(GraphQL::ExecutionError.new("This query is too large to execute."))
|
1668
1682
|
end
|
1669
1683
|
|
1670
1684
|
private
|
@@ -45,7 +45,8 @@ module GraphQL
|
|
45
45
|
# @param camelize [Boolean] if true, the name will be camelized when building the schema
|
46
46
|
# @param from_resolver [Boolean] if true, a Resolver class defined this argument
|
47
47
|
# @param method_access [Boolean] If false, don't build method access on legacy {Query::Arguments} instances.
|
48
|
-
|
48
|
+
# @param deprecation_reason [String]
|
49
|
+
def initialize(arg_name = nil, type_expr = nil, desc = nil, required:, type: nil, name: nil, loads: nil, description: nil, ast_node: nil, default_value: NO_DEFAULT, as: nil, from_resolver: false, camelize: true, prepare: nil, method_access: true, owner:, deprecation_reason: nil, &definition_block)
|
49
50
|
arg_name ||= name
|
50
51
|
@name = -(camelize ? Member::BuildType.camelize(arg_name.to_s) : arg_name.to_s)
|
51
52
|
@type_expr = type_expr || type
|
@@ -60,6 +61,7 @@ module GraphQL
|
|
60
61
|
@ast_node = ast_node
|
61
62
|
@from_resolver = from_resolver
|
62
63
|
@method_access = method_access
|
64
|
+
self.deprecation_reason = deprecation_reason
|
63
65
|
|
64
66
|
if definition_block
|
65
67
|
if definition_block.arity == 1
|
@@ -89,6 +91,18 @@ module GraphQL
|
|
89
91
|
end
|
90
92
|
end
|
91
93
|
|
94
|
+
# @return [String] Deprecation reason for this argument
|
95
|
+
def deprecation_reason(text = nil)
|
96
|
+
if text
|
97
|
+
validate_deprecated_or_optional(null: @null, deprecation_reason: text)
|
98
|
+
@deprecation_reason = text
|
99
|
+
else
|
100
|
+
@deprecation_reason
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
alias_method :deprecation_reason=, :deprecation_reason
|
105
|
+
|
92
106
|
def visible?(context)
|
93
107
|
true
|
94
108
|
end
|
@@ -143,15 +157,32 @@ module GraphQL
|
|
143
157
|
if NO_DEFAULT != @default_value
|
144
158
|
argument.default_value = @default_value
|
145
159
|
end
|
160
|
+
if @deprecation_reason
|
161
|
+
argument.deprecation_reason = @deprecation_reason
|
162
|
+
end
|
146
163
|
argument
|
147
164
|
end
|
148
165
|
|
149
|
-
|
166
|
+
def type=(new_type)
|
167
|
+
validate_input_type(new_type)
|
168
|
+
# This isn't true for LateBoundTypes, but we can assume those will
|
169
|
+
# be updated via this codepath later in schema setup.
|
170
|
+
if new_type.respond_to?(:non_null?)
|
171
|
+
validate_deprecated_or_optional(null: !new_type.non_null?, deprecation_reason: deprecation_reason)
|
172
|
+
end
|
173
|
+
@type = new_type
|
174
|
+
end
|
150
175
|
|
151
176
|
def type
|
152
|
-
@type ||=
|
153
|
-
|
154
|
-
|
177
|
+
@type ||= begin
|
178
|
+
parsed_type = begin
|
179
|
+
Member::BuildType.parse_type(@type_expr, null: @null)
|
180
|
+
rescue StandardError => err
|
181
|
+
raise ArgumentError, "Couldn't build type for Argument #{@owner.name}.#{name}: #{err.class.name}: #{err.message}", err.backtrace
|
182
|
+
end
|
183
|
+
# Use the setter method to get validations
|
184
|
+
self.type = parsed_type
|
185
|
+
end
|
155
186
|
end
|
156
187
|
|
157
188
|
def statically_coercible?
|
@@ -186,6 +217,26 @@ module GraphQL
|
|
186
217
|
raise "Invalid prepare for #{@owner.name}.name: #{@prepare.inspect}"
|
187
218
|
end
|
188
219
|
end
|
220
|
+
|
221
|
+
private
|
222
|
+
|
223
|
+
def validate_input_type(input_type)
|
224
|
+
if input_type.is_a?(String) || input_type.is_a?(GraphQL::Schema::LateBoundType)
|
225
|
+
# Do nothing; assume this will be validated later
|
226
|
+
elsif input_type.kind.non_null? || input_type.kind.list?
|
227
|
+
validate_input_type(input_type.unwrap)
|
228
|
+
elsif !input_type.kind.input?
|
229
|
+
raise ArgumentError, "Invalid input type for #{path}: #{input_type.graphql_name}. Must be scalar, enum, or input object, not #{input_type.kind.name}."
|
230
|
+
else
|
231
|
+
# It's an input type, we're OK
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
def validate_deprecated_or_optional(null:, deprecation_reason:)
|
236
|
+
if deprecation_reason && !null
|
237
|
+
raise ArgumentError, "Required arguments cannot be deprecated: #{path}."
|
238
|
+
end
|
239
|
+
end
|
189
240
|
end
|
190
241
|
end
|
191
242
|
end
|
@@ -4,17 +4,24 @@ require "graphql/schema/build_from_definition/resolve_map"
|
|
4
4
|
module GraphQL
|
5
5
|
class Schema
|
6
6
|
module BuildFromDefinition
|
7
|
+
if !String.method_defined?(:-@)
|
8
|
+
using GraphQL::StringDedupBackport
|
9
|
+
end
|
10
|
+
|
7
11
|
class << self
|
8
12
|
# @see {Schema.from_definition}
|
9
|
-
def from_definition(definition_string,
|
10
|
-
|
11
|
-
default_resolve ||= {}
|
12
|
-
Builder.build(document, default_resolve: default_resolve, relay: relay, using: using, interpreter: interpreter)
|
13
|
+
def from_definition(definition_string, parser: GraphQL.default_parser, **kwargs)
|
14
|
+
from_document(parser.parse(definition_string), **kwargs)
|
13
15
|
end
|
14
|
-
end
|
15
16
|
|
16
|
-
|
17
|
-
|
17
|
+
def from_definition_path(definition_path, parser: GraphQL.default_parser, **kwargs)
|
18
|
+
from_document(parser.parse_file(definition_path), **kwargs)
|
19
|
+
end
|
20
|
+
|
21
|
+
def from_document(document, default_resolve:, using: {}, relay: false, interpreter: true)
|
22
|
+
Builder.build(document, default_resolve: default_resolve || {}, relay: relay, using: using, interpreter: interpreter)
|
23
|
+
end
|
24
|
+
end
|
18
25
|
|
19
26
|
# @api private
|
20
27
|
module Builder
|
@@ -43,7 +50,7 @@ module GraphQL
|
|
43
50
|
when GraphQL::Language::Nodes::EnumTypeDefinition
|
44
51
|
types[definition.name] = build_enum_type(definition, type_resolver)
|
45
52
|
when GraphQL::Language::Nodes::ObjectTypeDefinition
|
46
|
-
types[definition.name] = build_object_type(definition, type_resolver
|
53
|
+
types[definition.name] = build_object_type(definition, type_resolver)
|
47
54
|
when GraphQL::Language::Nodes::InterfaceTypeDefinition
|
48
55
|
types[definition.name] = build_interface_type(definition, type_resolver)
|
49
56
|
when GraphQL::Language::Nodes::UnionTypeDefinition
|
@@ -111,11 +118,11 @@ module GraphQL
|
|
111
118
|
end
|
112
119
|
|
113
120
|
if default_resolve.respond_to?(:resolve_type)
|
114
|
-
|
115
|
-
|
121
|
+
def self.resolve_type(*args)
|
122
|
+
self.definition_default_resolve.resolve_type(*args)
|
116
123
|
end
|
117
124
|
else
|
118
|
-
|
125
|
+
def self.resolve_type(*args)
|
119
126
|
NullResolveType.call(*args)
|
120
127
|
end
|
121
128
|
end
|
@@ -141,6 +148,20 @@ module GraphQL
|
|
141
148
|
|
142
149
|
# Empty `orphan_types` -- this will make unreachable types ... unreachable.
|
143
150
|
own_orphan_types.clear
|
151
|
+
|
152
|
+
class << self
|
153
|
+
attr_accessor :definition_default_resolve
|
154
|
+
end
|
155
|
+
|
156
|
+
self.definition_default_resolve = default_resolve
|
157
|
+
|
158
|
+
def definition_default_resolve
|
159
|
+
self.class.definition_default_resolve
|
160
|
+
end
|
161
|
+
|
162
|
+
def self.inherited(child_class)
|
163
|
+
child_class.definition_default_resolve = self.definition_default_resolve
|
164
|
+
end
|
144
165
|
end
|
145
166
|
end
|
146
167
|
|
@@ -182,12 +203,12 @@ module GraphQL
|
|
182
203
|
ast_node(scalar_type_definition)
|
183
204
|
|
184
205
|
if default_resolve.respond_to?(:coerce_input)
|
185
|
-
|
186
|
-
|
206
|
+
def self.coerce_input(val, ctx)
|
207
|
+
ctx.schema.definition_default_resolve.coerce_input(self, val, ctx)
|
187
208
|
end
|
188
209
|
|
189
|
-
|
190
|
-
|
210
|
+
def self.coerce_result(val, ctx)
|
211
|
+
ctx.schema.definition_default_resolve.coerce_result(self, val, ctx)
|
191
212
|
end
|
192
213
|
end
|
193
214
|
end
|
@@ -202,13 +223,10 @@ module GraphQL
|
|
202
223
|
end
|
203
224
|
end
|
204
225
|
|
205
|
-
def build_object_type(object_type_definition, type_resolver
|
226
|
+
def build_object_type(object_type_definition, type_resolver)
|
206
227
|
builder = self
|
207
|
-
type_def = nil
|
208
|
-
typed_resolve_fn = ->(field, obj, args, ctx) { default_resolve.call(type_def, field, obj, args, ctx) }
|
209
228
|
|
210
229
|
Class.new(GraphQL::Schema::Object) do
|
211
|
-
type_def = self
|
212
230
|
graphql_name(object_type_definition.name)
|
213
231
|
description(object_type_definition.description)
|
214
232
|
ast_node(object_type_definition)
|
@@ -218,7 +236,7 @@ module GraphQL
|
|
218
236
|
implements(interface_defn)
|
219
237
|
end
|
220
238
|
|
221
|
-
builder.build_fields(self, object_type_definition.fields, type_resolver, default_resolve:
|
239
|
+
builder.build_fields(self, object_type_definition.fields, type_resolver, default_resolve: true)
|
222
240
|
end
|
223
241
|
end
|
224
242
|
|
@@ -247,13 +265,16 @@ module GraphQL
|
|
247
265
|
end
|
248
266
|
end
|
249
267
|
|
268
|
+
NO_DEFAULT_VALUE = {}.freeze
|
269
|
+
|
250
270
|
def build_arguments(type_class, arguments, type_resolver)
|
251
271
|
builder = self
|
252
272
|
|
253
273
|
arguments.each do |argument_defn|
|
254
|
-
default_value_kwargs =
|
255
|
-
|
256
|
-
|
274
|
+
default_value_kwargs = if !argument_defn.default_value.nil?
|
275
|
+
{ default_value: builder.build_default_value(argument_defn.default_value) }
|
276
|
+
else
|
277
|
+
NO_DEFAULT_VALUE
|
257
278
|
end
|
258
279
|
|
259
280
|
type_class.argument(
|
@@ -261,6 +282,7 @@ module GraphQL
|
|
261
282
|
type: type_resolver.call(argument_defn.type),
|
262
283
|
required: false,
|
263
284
|
description: argument_defn.description,
|
285
|
+
deprecation_reason: builder.build_deprecation_reason(argument_defn.directives),
|
264
286
|
ast_node: argument_defn,
|
265
287
|
camelize: false,
|
266
288
|
method_access: false,
|
@@ -295,10 +317,10 @@ module GraphQL
|
|
295
317
|
def build_fields(owner, field_definitions, type_resolver, default_resolve:)
|
296
318
|
builder = self
|
297
319
|
|
298
|
-
field_definitions.
|
320
|
+
field_definitions.each do |field_definition|
|
299
321
|
type_name = resolve_type_name(field_definition.type)
|
300
|
-
resolve_method_name = "resolve_field_#{field_definition.name}"
|
301
|
-
owner.field(
|
322
|
+
resolve_method_name = -"resolve_field_#{field_definition.name}"
|
323
|
+
schema_field_defn = owner.field(
|
302
324
|
field_definition.name,
|
303
325
|
description: field_definition.description,
|
304
326
|
type: type_resolver.call(field_definition.type),
|
@@ -310,16 +332,19 @@ module GraphQL
|
|
310
332
|
method_conflict_warning: false,
|
311
333
|
camelize: false,
|
312
334
|
resolver_method: resolve_method_name,
|
313
|
-
)
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
335
|
+
)
|
336
|
+
|
337
|
+
builder.build_arguments(schema_field_defn, field_definition.arguments, type_resolver)
|
338
|
+
|
339
|
+
# Don't do this for interfaces
|
340
|
+
if default_resolve
|
341
|
+
owner.class_eval <<-RUBY, __FILE__, __LINE__
|
342
|
+
# frozen_string_literal: true
|
343
|
+
def #{resolve_method_name}(**args)
|
344
|
+
field_instance = self.class.get_field("#{field_definition.name}")
|
345
|
+
context.schema.definition_default_resolve.call(self.class, field_instance, object, args, context)
|
321
346
|
end
|
322
|
-
|
347
|
+
RUBY
|
323
348
|
end
|
324
349
|
end
|
325
350
|
end
|