graphql 2.0.14 → 2.0.32
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/mutation_delete_generator.rb +1 -1
- data/lib/generators/graphql/mutation_update_generator.rb +1 -1
- data/lib/generators/graphql/relay.rb +18 -1
- data/lib/graphql/analysis/ast/visitor.rb +42 -35
- data/lib/graphql/analysis/ast.rb +2 -2
- data/lib/graphql/backtrace/table.rb +2 -2
- data/lib/graphql/backtrace/trace.rb +96 -0
- data/lib/graphql/backtrace/tracer.rb +1 -1
- data/lib/graphql/backtrace.rb +2 -1
- data/lib/graphql/dataloader/source.rb +69 -45
- data/lib/graphql/dataloader.rb +8 -5
- data/lib/graphql/execution/interpreter/arguments.rb +1 -1
- data/lib/graphql/execution/interpreter/arguments_cache.rb +33 -33
- data/lib/graphql/execution/interpreter/resolve.rb +19 -0
- data/lib/graphql/execution/interpreter/runtime.rb +355 -268
- data/lib/graphql/execution/interpreter.rb +19 -15
- data/lib/graphql/execution/lazy.rb +6 -12
- data/lib/graphql/execution/lookahead.rb +16 -5
- data/lib/graphql/execution/multiplex.rb +2 -1
- data/lib/graphql/filter.rb +8 -2
- data/lib/graphql/introspection/directive_type.rb +2 -2
- data/lib/graphql/introspection/entry_points.rb +1 -1
- data/lib/graphql/introspection/field_type.rb +1 -1
- data/lib/graphql/introspection/schema_type.rb +2 -2
- data/lib/graphql/introspection/type_type.rb +5 -5
- data/lib/graphql/introspection.rb +1 -1
- data/lib/graphql/language/document_from_schema_definition.rb +58 -35
- data/lib/graphql/language/lexer.rb +248 -1505
- data/lib/graphql/language/nodes.rb +69 -40
- data/lib/graphql/language/parser.rb +775 -742
- data/lib/graphql/language/parser.y +44 -38
- data/lib/graphql/language/printer.rb +48 -25
- data/lib/graphql/language/visitor.rb +192 -81
- data/lib/graphql/pagination/active_record_relation_connection.rb +0 -8
- data/lib/graphql/pagination/connection.rb +5 -5
- data/lib/graphql/query/context.rb +93 -27
- data/lib/graphql/query/null_context.rb +8 -18
- data/lib/graphql/query/validation_pipeline.rb +2 -1
- data/lib/graphql/query.rb +55 -13
- data/lib/graphql/rake_task.rb +28 -1
- data/lib/graphql/schema/addition.rb +38 -12
- data/lib/graphql/schema/always_visible.rb +10 -0
- data/lib/graphql/schema/argument.rb +15 -23
- data/lib/graphql/schema/build_from_definition.rb +54 -25
- data/lib/graphql/schema/directive/transform.rb +1 -1
- data/lib/graphql/schema/directive.rb +12 -2
- data/lib/graphql/schema/enum.rb +24 -17
- data/lib/graphql/schema/enum_value.rb +3 -4
- data/lib/graphql/schema/field/connection_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +95 -73
- data/lib/graphql/schema/field_extension.rb +1 -4
- data/lib/graphql/schema/find_inherited_value.rb +2 -7
- data/lib/graphql/schema/input_object.rb +9 -7
- data/lib/graphql/schema/interface.rb +5 -11
- data/lib/graphql/schema/introspection_system.rb +1 -1
- data/lib/graphql/schema/late_bound_type.rb +2 -0
- data/lib/graphql/schema/member/base_dsl_methods.rb +17 -14
- data/lib/graphql/schema/member/build_type.rb +11 -3
- data/lib/graphql/schema/member/has_arguments.rb +114 -65
- data/lib/graphql/schema/member/has_ast_node.rb +12 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +3 -4
- data/lib/graphql/schema/member/has_directives.rb +81 -61
- data/lib/graphql/schema/member/has_fields.rb +95 -38
- data/lib/graphql/schema/member/has_interfaces.rb +49 -8
- data/lib/graphql/schema/member/has_validators.rb +32 -6
- data/lib/graphql/schema/member/relay_shortcuts.rb +19 -0
- data/lib/graphql/schema/member/type_system_helpers.rb +17 -0
- data/lib/graphql/schema/object.rb +8 -5
- data/lib/graphql/schema/printer.rb +3 -1
- data/lib/graphql/schema/relay_classic_mutation.rb +1 -1
- data/lib/graphql/schema/resolver/has_payload_type.rb +9 -9
- data/lib/graphql/schema/resolver.rb +16 -14
- data/lib/graphql/schema/timeout.rb +25 -29
- data/lib/graphql/schema/type_membership.rb +3 -0
- data/lib/graphql/schema/union.rb +10 -1
- data/lib/graphql/schema/validator.rb +2 -2
- data/lib/graphql/schema/warden.rb +64 -7
- data/lib/graphql/schema.rb +171 -28
- data/lib/graphql/static_validation/definition_dependencies.rb +7 -1
- data/lib/graphql/static_validation/literal_validator.rb +15 -1
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +12 -4
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +2 -2
- data/lib/graphql/static_validation/validator.rb +1 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +7 -1
- data/lib/graphql/subscriptions/event.rb +2 -7
- data/lib/graphql/subscriptions.rb +5 -0
- data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
- data/lib/graphql/tracing/appoptics_trace.rb +255 -0
- data/lib/graphql/tracing/appsignal_trace.rb +81 -0
- data/lib/graphql/tracing/data_dog_trace.rb +187 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +7 -21
- data/lib/graphql/tracing/legacy_trace.rb +69 -0
- data/lib/graphql/tracing/new_relic_trace.rb +75 -0
- data/lib/graphql/tracing/notifications_trace.rb +49 -0
- data/lib/graphql/tracing/platform_trace.rb +123 -0
- data/lib/graphql/tracing/platform_tracing.rb +15 -3
- data/lib/graphql/tracing/prometheus_trace.rb +93 -0
- data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +1 -1
- data/lib/graphql/tracing/prometheus_tracing.rb +3 -3
- data/lib/graphql/tracing/scout_trace.rb +75 -0
- data/lib/graphql/tracing/statsd_trace.rb +60 -0
- data/lib/graphql/tracing/trace.rb +75 -0
- data/lib/graphql/tracing.rb +17 -39
- data/lib/graphql/type_kinds.rb +6 -3
- data/lib/graphql/types/relay/base_connection.rb +1 -1
- data/lib/graphql/types/relay/connection_behaviors.rb +28 -6
- data/lib/graphql/types/relay/edge_behaviors.rb +16 -5
- data/lib/graphql/types/relay/node_behaviors.rb +8 -2
- data/lib/graphql/types/relay/page_info_behaviors.rb +7 -2
- data/lib/graphql/types/relay.rb +0 -1
- data/lib/graphql/types/string.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +16 -9
- data/readme.md +1 -1
- metadata +66 -29
- data/lib/graphql/language/lexer.rl +0 -280
- data/lib/graphql/types/relay/default_relay.rb +0 -21
|
@@ -109,7 +109,14 @@ module GraphQL
|
|
|
109
109
|
to_type_name(something.name)
|
|
110
110
|
end
|
|
111
111
|
when String
|
|
112
|
-
something.
|
|
112
|
+
if something.include?("]") ||
|
|
113
|
+
something.include?("[") ||
|
|
114
|
+
something.include?("!") ||
|
|
115
|
+
something.include?("::")
|
|
116
|
+
something.gsub(/\]\[\!/, "").split("::").last
|
|
117
|
+
else
|
|
118
|
+
something
|
|
119
|
+
end
|
|
113
120
|
when GraphQL::Schema::NonNull, GraphQL::Schema::List
|
|
114
121
|
to_type_name(something.unwrap)
|
|
115
122
|
else
|
|
@@ -120,9 +127,10 @@ module GraphQL
|
|
|
120
127
|
def camelize(string)
|
|
121
128
|
return string if string == '_'
|
|
122
129
|
return string unless string.include?("_")
|
|
123
|
-
camelized = string.split('_').
|
|
130
|
+
camelized = string.split('_').each(&:capitalize!).join
|
|
124
131
|
camelized[0] = camelized[0].downcase
|
|
125
|
-
if
|
|
132
|
+
if string.start_with?("_")
|
|
133
|
+
match_data = string.match(/\A(_+)/)
|
|
126
134
|
camelized = "#{match_data[0]}#{camelized}"
|
|
127
135
|
end
|
|
128
136
|
camelized
|
|
@@ -11,6 +11,7 @@ module GraphQL
|
|
|
11
11
|
def self.extended(cls)
|
|
12
12
|
cls.extend(ArgumentClassAccessor)
|
|
13
13
|
cls.include(ArgumentObjectLoader)
|
|
14
|
+
cls.extend(ClassConfigured)
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
# @see {GraphQL::Schema::Argument#initialize} for parameters
|
|
@@ -50,7 +51,7 @@ module GraphQL
|
|
|
50
51
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
51
52
|
def #{method_owner}load_#{arg_defn.keyword}(values, context = nil)
|
|
52
53
|
argument = get_argument("#{arg_defn.graphql_name}")
|
|
53
|
-
(context || self.context).
|
|
54
|
+
(context || self.context).query.after_lazy(values) do |values2|
|
|
54
55
|
GraphQL::Execution::Lazy.all(values2.map { |value| load_application_object(argument, value, context || self.context) })
|
|
55
56
|
end
|
|
56
57
|
end
|
|
@@ -109,14 +110,6 @@ module GraphQL
|
|
|
109
110
|
|
|
110
111
|
# @return [Hash<String => GraphQL::Schema::Argument] Arguments defined on this thing, keyed by name. Includes inherited definitions
|
|
111
112
|
def arguments(context = GraphQL::Query::NullContext)
|
|
112
|
-
inherited_arguments = if self.is_a?(Class) && superclass.respond_to?(:arguments)
|
|
113
|
-
superclass.arguments(context)
|
|
114
|
-
elsif defined?(@resolver_class) && @resolver_class
|
|
115
|
-
@resolver_class.field_arguments(context)
|
|
116
|
-
else
|
|
117
|
-
nil
|
|
118
|
-
end
|
|
119
|
-
# Local definitions override inherited ones
|
|
120
113
|
if own_arguments.any?
|
|
121
114
|
own_arguments_that_apply = {}
|
|
122
115
|
own_arguments.each do |name, args_entry|
|
|
@@ -125,47 +118,107 @@ module GraphQL
|
|
|
125
118
|
end
|
|
126
119
|
end
|
|
127
120
|
end
|
|
121
|
+
# might be nil if there are actually no arguments
|
|
122
|
+
own_arguments_that_apply || own_arguments
|
|
123
|
+
end
|
|
128
124
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
125
|
+
module ClassConfigured
|
|
126
|
+
def inherited(child_class)
|
|
127
|
+
super
|
|
128
|
+
child_class.extend(InheritedArguments)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
module InheritedArguments
|
|
132
|
+
def arguments(context = GraphQL::Query::NullContext)
|
|
133
|
+
own_arguments = super
|
|
134
|
+
inherited_arguments = superclass.arguments(context)
|
|
135
|
+
|
|
136
|
+
if own_arguments.any?
|
|
137
|
+
if inherited_arguments.any?
|
|
138
|
+
# Local definitions override inherited ones
|
|
139
|
+
inherited_arguments.merge(own_arguments)
|
|
140
|
+
else
|
|
141
|
+
own_arguments
|
|
142
|
+
end
|
|
143
|
+
else
|
|
144
|
+
inherited_arguments
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def all_argument_definitions
|
|
149
|
+
all_defns = {}
|
|
150
|
+
ancestors.reverse_each do |ancestor|
|
|
151
|
+
if ancestor.respond_to?(:own_arguments)
|
|
152
|
+
all_defns.merge!(ancestor.own_arguments)
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
all_defns = all_defns.values
|
|
156
|
+
all_defns.flatten!
|
|
157
|
+
all_defns
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def get_argument(argument_name, context = GraphQL::Query::NullContext)
|
|
162
|
+
warden = Warden.from_context(context)
|
|
163
|
+
for ancestor in ancestors
|
|
164
|
+
if ancestor.respond_to?(:own_arguments) &&
|
|
165
|
+
(a = ancestor.own_arguments[argument_name]) &&
|
|
166
|
+
(a = Warden.visible_entry?(:visible_argument?, a, context, warden))
|
|
167
|
+
return a
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
nil
|
|
134
171
|
end
|
|
135
|
-
else
|
|
136
|
-
# might be nil if there are actually no arguments
|
|
137
|
-
own_arguments_that_apply || own_arguments
|
|
138
172
|
end
|
|
139
173
|
end
|
|
140
174
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
175
|
+
module FieldConfigured
|
|
176
|
+
def arguments(context = GraphQL::Query::NullContext)
|
|
177
|
+
own_arguments = super
|
|
178
|
+
if defined?(@resolver_class) && @resolver_class
|
|
179
|
+
inherited_arguments = @resolver_class.field_arguments(context)
|
|
180
|
+
if own_arguments.any?
|
|
181
|
+
if inherited_arguments.any?
|
|
182
|
+
inherited_arguments.merge(own_arguments)
|
|
183
|
+
else
|
|
184
|
+
own_arguments
|
|
185
|
+
end
|
|
186
|
+
else
|
|
187
|
+
inherited_arguments
|
|
147
188
|
end
|
|
189
|
+
else
|
|
190
|
+
own_arguments
|
|
148
191
|
end
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def all_argument_definitions
|
|
195
|
+
if defined?(@resolver_class) && @resolver_class
|
|
196
|
+
all_defns = {}
|
|
197
|
+
@resolver_class.all_field_argument_definitions.each do |arg_defn|
|
|
198
|
+
key = arg_defn.graphql_name
|
|
199
|
+
case (current_value = all_defns[key])
|
|
200
|
+
when nil
|
|
201
|
+
all_defns[key] = arg_defn
|
|
202
|
+
when Array
|
|
203
|
+
current_value << arg_defn
|
|
204
|
+
when GraphQL::Schema::Argument
|
|
205
|
+
all_defns[key] = [current_value, arg_defn]
|
|
206
|
+
else
|
|
207
|
+
raise "Invariant: Unexpected argument definition, #{current_value.class}: #{current_value.inspect}"
|
|
208
|
+
end
|
|
162
209
|
end
|
|
210
|
+
all_defns.merge!(own_arguments)
|
|
211
|
+
all_defns = all_defns.values
|
|
212
|
+
all_defns.flatten!
|
|
213
|
+
all_defns
|
|
214
|
+
else
|
|
215
|
+
super
|
|
163
216
|
end
|
|
164
|
-
all_defns.merge!(own_arguments)
|
|
165
|
-
else
|
|
166
|
-
all_defns = own_arguments
|
|
167
217
|
end
|
|
168
|
-
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def all_argument_definitions
|
|
221
|
+
all_defns = own_arguments.values
|
|
169
222
|
all_defns.flatten!
|
|
170
223
|
all_defns
|
|
171
224
|
end
|
|
@@ -173,22 +226,11 @@ module GraphQL
|
|
|
173
226
|
# @return [GraphQL::Schema::Argument, nil] Argument defined on this thing, fetched by name.
|
|
174
227
|
def get_argument(argument_name, context = GraphQL::Query::NullContext)
|
|
175
228
|
warden = Warden.from_context(context)
|
|
176
|
-
if
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
@resolver_class.get_field_argument(argument_name, context)
|
|
181
|
-
else
|
|
182
|
-
nil
|
|
183
|
-
end
|
|
229
|
+
if (arg_config = own_arguments[argument_name]) && (visible_arg = Warden.visible_entry?(:visible_argument?, arg_config, context, warden))
|
|
230
|
+
visible_arg
|
|
231
|
+
elsif defined?(@resolver_class) && @resolver_class
|
|
232
|
+
@resolver_class.get_field_argument(argument_name, context)
|
|
184
233
|
else
|
|
185
|
-
for ancestor in ancestors
|
|
186
|
-
if ancestor.respond_to?(:own_arguments) &&
|
|
187
|
-
(a = ancestor.own_arguments[argument_name]) &&
|
|
188
|
-
(a = Warden.visible_entry?(:visible_argument?, a, context, warden))
|
|
189
|
-
return a
|
|
190
|
-
end
|
|
191
|
-
end
|
|
192
234
|
nil
|
|
193
235
|
end
|
|
194
236
|
end
|
|
@@ -209,7 +251,7 @@ module GraphQL
|
|
|
209
251
|
# @return [Interpreter::Arguments, Execution::Lazy<Interpeter::Arguments>]
|
|
210
252
|
def coerce_arguments(parent_object, values, context, &block)
|
|
211
253
|
# Cache this hash to avoid re-merging it
|
|
212
|
-
arg_defns =
|
|
254
|
+
arg_defns = context.warden.arguments(self)
|
|
213
255
|
total_args_count = arg_defns.size
|
|
214
256
|
|
|
215
257
|
finished_args = nil
|
|
@@ -223,7 +265,7 @@ module GraphQL
|
|
|
223
265
|
argument_values = {}
|
|
224
266
|
resolved_args_count = 0
|
|
225
267
|
raised_error = false
|
|
226
|
-
arg_defns.each do |
|
|
268
|
+
arg_defns.each do |arg_defn|
|
|
227
269
|
context.dataloader.append_job do
|
|
228
270
|
begin
|
|
229
271
|
arg_defn.coerce_into_values(parent_object, values, context, argument_values)
|
|
@@ -265,7 +307,12 @@ module GraphQL
|
|
|
265
307
|
# but not for directives.
|
|
266
308
|
# TODO apply static validations on schema definitions?
|
|
267
309
|
def validate_directive_argument(arg_defn, value)
|
|
268
|
-
|
|
310
|
+
# this is only implemented on directives.
|
|
311
|
+
nil
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
module HasDirectiveArguments
|
|
315
|
+
def validate_directive_argument(arg_defn, value)
|
|
269
316
|
if value.nil? && arg_defn.type.non_null?
|
|
270
317
|
raise ArgumentError, "#{arg_defn.path} is required, but no value was given"
|
|
271
318
|
end
|
|
@@ -273,9 +320,11 @@ module GraphQL
|
|
|
273
320
|
end
|
|
274
321
|
|
|
275
322
|
def arguments_statically_coercible?
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
323
|
+
if defined?(@arguments_statically_coercible) && !@arguments_statically_coercible.nil?
|
|
324
|
+
@arguments_statically_coercible
|
|
325
|
+
else
|
|
326
|
+
@arguments_statically_coercible = all_argument_definitions.all?(&:statically_coercible?)
|
|
327
|
+
end
|
|
279
328
|
end
|
|
280
329
|
|
|
281
330
|
module ArgumentClassAccessor
|
|
@@ -316,7 +365,7 @@ module GraphQL
|
|
|
316
365
|
end
|
|
317
366
|
|
|
318
367
|
def authorize_application_object(argument, id, context, loaded_application_object)
|
|
319
|
-
context.
|
|
368
|
+
context.query.after_lazy(loaded_application_object) do |application_object|
|
|
320
369
|
if application_object.nil?
|
|
321
370
|
err = GraphQL::LoadApplicationObjectFailedError.new(argument: argument, id: id, object: application_object)
|
|
322
371
|
load_application_object_failed(err)
|
|
@@ -324,7 +373,7 @@ module GraphQL
|
|
|
324
373
|
# Double-check that the located object is actually of this type
|
|
325
374
|
# (Don't want to allow arbitrary access to objects this way)
|
|
326
375
|
maybe_lazy_resolve_type = context.schema.resolve_type(argument.loads, application_object, context)
|
|
327
|
-
context.
|
|
376
|
+
context.query.after_lazy(maybe_lazy_resolve_type) do |resolve_type_result|
|
|
328
377
|
if resolve_type_result.is_a?(Array) && resolve_type_result.size == 2
|
|
329
378
|
application_object_type, application_object = resolve_type_result
|
|
330
379
|
else
|
|
@@ -339,7 +388,7 @@ module GraphQL
|
|
|
339
388
|
# This object was loaded successfully
|
|
340
389
|
# and resolved to the right type,
|
|
341
390
|
# now apply the `.authorized?` class method if there is one
|
|
342
|
-
context.
|
|
391
|
+
context.query.after_lazy(application_object_type.authorized?(application_object, context)) do |authed|
|
|
343
392
|
if authed
|
|
344
393
|
application_object
|
|
345
394
|
else
|
|
@@ -366,7 +415,7 @@ module GraphQL
|
|
|
366
415
|
end
|
|
367
416
|
end
|
|
368
417
|
|
|
369
|
-
NO_ARGUMENTS =
|
|
418
|
+
NO_ARGUMENTS = GraphQL::EmptyObjects::EMPTY_HASH
|
|
370
419
|
def own_arguments
|
|
371
420
|
@own_arguments || NO_ARGUMENTS
|
|
372
421
|
end
|
|
@@ -3,6 +3,16 @@ module GraphQL
|
|
|
3
3
|
class Schema
|
|
4
4
|
class Member
|
|
5
5
|
module HasAstNode
|
|
6
|
+
def self.extended(child_cls)
|
|
7
|
+
super
|
|
8
|
+
child_cls.ast_node = nil
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def inherited(child_cls)
|
|
12
|
+
super
|
|
13
|
+
child_cls.ast_node = nil
|
|
14
|
+
end
|
|
15
|
+
|
|
6
16
|
# If this schema was parsed from a `.graphql` file (or other SDL),
|
|
7
17
|
# this is the AST node that defined this part of the schema.
|
|
8
18
|
def ast_node(new_ast_node = nil)
|
|
@@ -14,6 +24,8 @@ module GraphQL
|
|
|
14
24
|
nil
|
|
15
25
|
end
|
|
16
26
|
end
|
|
27
|
+
|
|
28
|
+
attr_writer :ast_node
|
|
17
29
|
end
|
|
18
30
|
end
|
|
19
31
|
end
|
|
@@ -5,17 +5,16 @@ module GraphQL
|
|
|
5
5
|
class Member
|
|
6
6
|
module HasDeprecationReason
|
|
7
7
|
# @return [String, nil] Explains why this member was deprecated (if present, this will be marked deprecated in introspection)
|
|
8
|
-
|
|
9
|
-
dir = self.directives.find { |d| d.is_a?(GraphQL::Schema::Directive::Deprecated) }
|
|
10
|
-
dir && dir.arguments[:reason] # rubocop:disable Development/ContextIsPassedCop -- definition-related
|
|
11
|
-
end
|
|
8
|
+
attr_reader :deprecation_reason
|
|
12
9
|
|
|
13
10
|
# Set the deprecation reason for this member, or remove it by assigning `nil`
|
|
14
11
|
# @param text [String, nil]
|
|
15
12
|
def deprecation_reason=(text)
|
|
13
|
+
@deprecation_reason = text
|
|
16
14
|
if text.nil?
|
|
17
15
|
remove_directive(GraphQL::Schema::Directive::Deprecated)
|
|
18
16
|
else
|
|
17
|
+
# This removes a previously-attached directive, if there is one:
|
|
19
18
|
directive(GraphQL::Schema::Directive::Deprecated, reason: text)
|
|
20
19
|
end
|
|
21
20
|
end
|
|
@@ -4,6 +4,16 @@ module GraphQL
|
|
|
4
4
|
class Schema
|
|
5
5
|
class Member
|
|
6
6
|
module HasDirectives
|
|
7
|
+
def self.extended(child_cls)
|
|
8
|
+
super
|
|
9
|
+
child_cls.module_exec { self.own_directives = nil }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def inherited(child_cls)
|
|
13
|
+
super
|
|
14
|
+
child_cls.own_directives = nil
|
|
15
|
+
end
|
|
16
|
+
|
|
7
17
|
# Create an instance of `dir_class` for `self`, using `options`.
|
|
8
18
|
#
|
|
9
19
|
# It removes a previously-attached instance of `dir_class`, if there is one.
|
|
@@ -11,8 +21,7 @@ module GraphQL
|
|
|
11
21
|
# @return [void]
|
|
12
22
|
def directive(dir_class, **options)
|
|
13
23
|
@own_directives ||= []
|
|
14
|
-
|
|
15
|
-
@own_directives << dir_class.new(self, **options)
|
|
24
|
+
HasDirectives.add_directive(self, @own_directives, dir_class, options)
|
|
16
25
|
nil
|
|
17
26
|
end
|
|
18
27
|
|
|
@@ -20,78 +29,89 @@ module GraphQL
|
|
|
20
29
|
# @param dir_class [Class<GraphQL::Schema::Directive>]
|
|
21
30
|
# @return [viod]
|
|
22
31
|
def remove_directive(dir_class)
|
|
23
|
-
@own_directives
|
|
32
|
+
HasDirectives.remove_directive(@own_directives, dir_class)
|
|
24
33
|
nil
|
|
25
34
|
end
|
|
26
35
|
|
|
27
|
-
NO_DIRECTIVES = [].freeze
|
|
28
|
-
|
|
29
36
|
def directives
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
37
|
+
HasDirectives.get_directives(self, @own_directives, :directives)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class << self
|
|
41
|
+
def add_directive(schema_member, directives, directive_class, directive_options)
|
|
42
|
+
remove_directive(directives, directive_class) unless directive_class.repeatable?
|
|
43
|
+
directives << directive_class.new(schema_member, **directive_options)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def remove_directive(directives, directive_class)
|
|
47
|
+
directives && directives.reject! { |d| d.is_a?(directive_class) }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def get_directives(schema_member, directives, directives_method)
|
|
51
|
+
case schema_member
|
|
52
|
+
when Class
|
|
53
|
+
inherited_directives = if schema_member.superclass.respond_to?(directives_method)
|
|
54
|
+
get_directives(schema_member.superclass, schema_member.superclass.public_send(directives_method), directives_method)
|
|
55
|
+
else
|
|
56
|
+
GraphQL::EmptyObjects::EMPTY_ARRAY
|
|
57
|
+
end
|
|
58
|
+
if inherited_directives.any? && directives
|
|
59
|
+
dirs = []
|
|
60
|
+
merge_directives(dirs, inherited_directives)
|
|
61
|
+
merge_directives(dirs, directives)
|
|
62
|
+
dirs
|
|
63
|
+
elsif directives
|
|
64
|
+
directives
|
|
65
|
+
elsif inherited_directives.any?
|
|
66
|
+
inherited_directives
|
|
67
|
+
else
|
|
68
|
+
GraphQL::EmptyObjects::EMPTY_ARRAY
|
|
69
|
+
end
|
|
70
|
+
when Module
|
|
71
|
+
dirs = nil
|
|
72
|
+
schema_member.ancestors.reverse_each do |ancestor|
|
|
73
|
+
if ancestor.respond_to?(:own_directives) &&
|
|
74
|
+
(anc_dirs = ancestor.own_directives).any?
|
|
75
|
+
dirs ||= []
|
|
76
|
+
merge_directives(dirs, anc_dirs)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
if directives
|
|
54
80
|
dirs ||= []
|
|
55
|
-
merge_directives(dirs,
|
|
81
|
+
merge_directives(dirs, directives)
|
|
56
82
|
end
|
|
83
|
+
dirs || GraphQL::EmptyObjects::EMPTY_ARRAY
|
|
84
|
+
when HasDirectives
|
|
85
|
+
directives || GraphQL::EmptyObjects::EMPTY_ARRAY
|
|
86
|
+
else
|
|
87
|
+
raise "Invariant: how could #{schema_member} not be a Class, Module, or instance of HasDirectives?"
|
|
57
88
|
end
|
|
58
|
-
if own_directives
|
|
59
|
-
dirs ||= []
|
|
60
|
-
merge_directives(dirs, own_directives)
|
|
61
|
-
end
|
|
62
|
-
dirs || NO_DIRECTIVES
|
|
63
|
-
when HasDirectives
|
|
64
|
-
@own_directives || NO_DIRECTIVES
|
|
65
|
-
else
|
|
66
|
-
raise "Invariant: how could #{self} not be a Class, Module, or instance of HasDirectives?"
|
|
67
89
|
end
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
protected
|
|
71
|
-
|
|
72
|
-
def own_directives
|
|
73
|
-
@own_directives
|
|
74
|
-
end
|
|
75
90
|
|
|
76
|
-
|
|
91
|
+
private
|
|
77
92
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
93
|
+
# Modify `target` by adding items from `dirs` such that:
|
|
94
|
+
# - Any name conflict is overriden by the incoming member of `dirs`
|
|
95
|
+
# - Any other member of `dirs` is appended
|
|
96
|
+
# @param target [Array<GraphQL::Schema::Directive>]
|
|
97
|
+
# @param dirs [Array<GraphQL::Schema::Directive>]
|
|
98
|
+
# @return [void]
|
|
99
|
+
def merge_directives(target, dirs)
|
|
100
|
+
dirs.each do |dir|
|
|
101
|
+
if (idx = target.find_index { |d| d.graphql_name == dir.graphql_name })
|
|
102
|
+
target.slice!(idx)
|
|
103
|
+
target.insert(idx, dir)
|
|
104
|
+
else
|
|
105
|
+
target << dir
|
|
106
|
+
end
|
|
91
107
|
end
|
|
108
|
+
nil
|
|
92
109
|
end
|
|
93
|
-
nil
|
|
94
110
|
end
|
|
111
|
+
|
|
112
|
+
protected
|
|
113
|
+
|
|
114
|
+
attr_accessor :own_directives
|
|
95
115
|
end
|
|
96
116
|
end
|
|
97
117
|
end
|