graphql 2.3.14 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/orm_mutations_base.rb +1 -1
  3. data/lib/generators/graphql/templates/base_resolver.erb +2 -0
  4. data/lib/generators/graphql/type_generator.rb +1 -1
  5. data/lib/graphql/analysis.rb +1 -1
  6. data/lib/graphql/dataloader/async_dataloader.rb +3 -2
  7. data/lib/graphql/dataloader/source.rb +1 -1
  8. data/lib/graphql/dataloader.rb +31 -10
  9. data/lib/graphql/execution/interpreter/resolve.rb +10 -6
  10. data/lib/graphql/invalid_null_error.rb +1 -1
  11. data/lib/graphql/language/comment.rb +18 -0
  12. data/lib/graphql/language/document_from_schema_definition.rb +38 -4
  13. data/lib/graphql/language/lexer.rb +15 -12
  14. data/lib/graphql/language/nodes.rb +22 -14
  15. data/lib/graphql/language/parser.rb +5 -0
  16. data/lib/graphql/language/printer.rb +23 -7
  17. data/lib/graphql/language.rb +6 -5
  18. data/lib/graphql/query/null_context.rb +1 -1
  19. data/lib/graphql/query.rb +49 -16
  20. data/lib/graphql/rubocop/graphql/field_type_in_block.rb +23 -8
  21. data/lib/graphql/schema/always_visible.rb +6 -3
  22. data/lib/graphql/schema/argument.rb +14 -1
  23. data/lib/graphql/schema/build_from_definition.rb +1 -0
  24. data/lib/graphql/schema/enum.rb +3 -0
  25. data/lib/graphql/schema/enum_value.rb +9 -1
  26. data/lib/graphql/schema/field.rb +35 -14
  27. data/lib/graphql/schema/input_object.rb +20 -7
  28. data/lib/graphql/schema/interface.rb +1 -0
  29. data/lib/graphql/schema/member/base_dsl_methods.rb +15 -0
  30. data/lib/graphql/schema/member/has_arguments.rb +2 -2
  31. data/lib/graphql/schema/member/has_fields.rb +2 -2
  32. data/lib/graphql/schema/printer.rb +1 -0
  33. data/lib/graphql/schema/resolver.rb +3 -4
  34. data/lib/graphql/schema/validator/required_validator.rb +28 -4
  35. data/lib/graphql/schema/visibility/migration.rb +186 -0
  36. data/lib/graphql/schema/visibility/profile.rb +523 -0
  37. data/lib/graphql/schema/visibility.rb +75 -0
  38. data/lib/graphql/schema/warden.rb +77 -15
  39. data/lib/graphql/schema.rb +203 -61
  40. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +2 -1
  41. data/lib/graphql/static_validation/rules/directives_are_defined.rb +2 -1
  42. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +2 -0
  43. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +2 -1
  44. data/lib/graphql/static_validation/rules/fields_will_merge.rb +1 -0
  45. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +11 -1
  46. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +10 -1
  47. data/lib/graphql/static_validation/validation_context.rb +15 -0
  48. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +2 -1
  49. data/lib/graphql/subscriptions.rb +3 -1
  50. data/lib/graphql/testing/helpers.rb +2 -1
  51. data/lib/graphql/tracing/notifications_trace.rb +2 -2
  52. data/lib/graphql/version.rb +1 -1
  53. metadata +11 -9
  54. data/lib/graphql/schema/subset.rb +0 -509
  55. data/lib/graphql/schema/types_migration.rb +0 -187
@@ -250,6 +250,8 @@ module GraphQL
250
250
  def normalize_arguments(event_name, arg_owner, args, context)
251
251
  case arg_owner
252
252
  when GraphQL::Schema::Field, Class
253
+ return args if args.nil?
254
+
253
255
  if arg_owner.is_a?(Class) && !arg_owner.kind.input_object?
254
256
  # it's a type, but not an input object
255
257
  return args
@@ -302,7 +304,7 @@ module GraphQL
302
304
 
303
305
  normalized_args
304
306
  when GraphQL::Schema::List
305
- args.map { |a| normalize_arguments(event_name, arg_owner.of_type, a, context) }
307
+ args&.map { |a| normalize_arguments(event_name, arg_owner.of_type, a, context) }
306
308
  when GraphQL::Schema::NonNull
307
309
  normalize_arguments(event_name, arg_owner.of_type, args, context)
308
310
  else
@@ -55,6 +55,7 @@ module GraphQL
55
55
  visible_field = dummy_query.types.field(object_type, field_name) # rubocop:disable Development/ContextIsPassedCop
56
56
  if visible_field
57
57
  dummy_query.context.dataloader.run_isolated {
58
+ query_context[:current_field] = visible_field
58
59
  field_args = visible_field.coerce_arguments(graphql_result, arguments, query_context)
59
60
  field_args = schema.sync_lazy(field_args)
60
61
  if visible_field.extras.any?
@@ -91,7 +92,7 @@ module GraphQL
91
92
  end
92
93
  graphql_result
93
94
  else
94
- unfiltered_type = Schema::Subset.pass_thru(schema: schema, context: context).type(type_name)
95
+ unfiltered_type = Schema::Visibility::Profile.pass_thru(schema: schema, context: context).type(type_name)
95
96
  if unfiltered_type
96
97
  raise TypeNotVisibleError.new(type_name: type_name)
97
98
  else
@@ -33,8 +33,8 @@ module GraphQL
33
33
  "resolve_type_lazy" => "resolve_type.graphql",
34
34
  }.each do |trace_method, platform_key|
35
35
  module_eval <<-RUBY, __FILE__, __LINE__
36
- def #{trace_method}(**metadata, &blk)
37
- @notifications_engine.instrument("#{platform_key}", metadata, &blk)
36
+ def #{trace_method}(**metadata, &block)
37
+ @notifications_engine.instrument("#{platform_key}", metadata) { super(**metadata, &block) }
38
38
  end
39
39
  RUBY
40
40
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "2.3.14"
3
+ VERSION = "2.4.0"
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.14
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-08-13 00:00:00.000000000 Z
11
+ date: 2024-10-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64
@@ -168,16 +168,16 @@ dependencies:
168
168
  name: rubocop
169
169
  requirement: !ruby/object:Gem::Requirement
170
170
  requirements:
171
- - - '='
171
+ - - ">="
172
172
  - !ruby/object:Gem::Version
173
- version: '1.12'
173
+ version: '0'
174
174
  type: :development
175
175
  prerelease: false
176
176
  version_requirements: !ruby/object:Gem::Requirement
177
177
  requirements:
178
- - - '='
178
+ - - ">="
179
179
  - !ruby/object:Gem::Version
180
- version: '1.12'
180
+ version: '0'
181
181
  - !ruby/object:Gem::Dependency
182
182
  name: jekyll
183
183
  requirement: !ruby/object:Gem::Requirement
@@ -382,6 +382,7 @@ files:
382
382
  - lib/graphql/language.rb
383
383
  - lib/graphql/language/block_string.rb
384
384
  - lib/graphql/language/cache.rb
385
+ - lib/graphql/language/comment.rb
385
386
  - lib/graphql/language/definition_slice.rb
386
387
  - lib/graphql/language/document_from_schema_definition.rb
387
388
  - lib/graphql/language/generation.rb
@@ -485,11 +486,9 @@ files:
485
486
  - lib/graphql/schema/resolver/has_payload_type.rb
486
487
  - lib/graphql/schema/scalar.rb
487
488
  - lib/graphql/schema/subscription.rb
488
- - lib/graphql/schema/subset.rb
489
489
  - lib/graphql/schema/timeout.rb
490
490
  - lib/graphql/schema/type_expression.rb
491
491
  - lib/graphql/schema/type_membership.rb
492
- - lib/graphql/schema/types_migration.rb
493
492
  - lib/graphql/schema/union.rb
494
493
  - lib/graphql/schema/unique_within_type.rb
495
494
  - lib/graphql/schema/validator.rb
@@ -502,6 +501,9 @@ files:
502
501
  - lib/graphql/schema/validator/length_validator.rb
503
502
  - lib/graphql/schema/validator/numericality_validator.rb
504
503
  - lib/graphql/schema/validator/required_validator.rb
504
+ - lib/graphql/schema/visibility.rb
505
+ - lib/graphql/schema/visibility/migration.rb
506
+ - lib/graphql/schema/visibility/profile.rb
505
507
  - lib/graphql/schema/warden.rb
506
508
  - lib/graphql/schema/wrapper.rb
507
509
  - lib/graphql/static_validation.rb
@@ -663,7 +665,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
663
665
  - !ruby/object:Gem::Version
664
666
  version: '0'
665
667
  requirements: []
666
- rubygems_version: 3.3.7
668
+ rubygems_version: 3.5.12
667
669
  signing_key:
668
670
  specification_version: 4
669
671
  summary: A GraphQL language and runtime for Ruby
@@ -1,509 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module GraphQL
4
- class Schema
5
- # This class filters the types, fields, arguments, enum values, and directives in a schema
6
- # based on the given `context`.
7
- #
8
- # It's like {Warden}, but has some differences:
9
- #
10
- # - It doesn't use {Schema}'s top-level caches (eg {Schema.references_to}, {Schema.possible_types}, {Schema.types})
11
- # - It doesn't hide Interface or Union types when all their possible types are hidden. (Instead, those types should implement `.visible?` to hide in that case.)
12
- # - It checks `.visible?` on root introspection types
13
- #
14
- # In the future, {Subset} will support lazy-loading types as needed during execution and multi-request caching of subsets.
15
- #
16
- # @see Schema::TypesMigration for a helper class in adopting this filter
17
- class Subset
18
- # @return [Schema::Subset]
19
- def self.from_context(ctx, schema)
20
- if ctx.respond_to?(:types) && (types = ctx.types).is_a?(self)
21
- types
22
- else
23
- # TODO use a cached instance from the schema
24
- self.new(context: ctx, schema: schema)
25
- end
26
- end
27
-
28
- def self.pass_thru(context:, schema:)
29
- subset = self.new(context: context, schema: schema)
30
- subset.instance_variable_set(:@cached_visible, Hash.new { |h,k| h[k] = true })
31
- subset
32
- end
33
-
34
- def initialize(context:, schema:)
35
- @context = context
36
- @schema = schema
37
- @all_types = {}
38
- @all_types_loaded = false
39
- @unvisited_types = []
40
- @referenced_types = Hash.new { |h, type_defn| h[type_defn] = [] }.compare_by_identity
41
- @cached_directives = {}
42
- @all_directives = nil
43
- @cached_visible = Hash.new { |h, member|
44
- h[member] = @schema.visible?(member, @context)
45
- }.compare_by_identity
46
-
47
- @cached_visible_fields = Hash.new { |h, owner|
48
- h[owner] = Hash.new do |h2, field|
49
- h2[field] = if @cached_visible[field] &&
50
- (ret_type = field.type.unwrap) &&
51
- @cached_visible[ret_type] &&
52
- (owner == field.owner || (!owner.kind.object?) || field_on_visible_interface?(field, owner))
53
-
54
- if !field.introspection?
55
- # The problem is that some introspection fields may have references
56
- # to non-custom introspection types.
57
- # If those were added here, they'd cause a DuplicateNamesError.
58
- # This is basically a bug -- those fields _should_ reference the custom types.
59
- add_type(ret_type, field)
60
- end
61
- true
62
- else
63
- false
64
- end
65
- end.compare_by_identity
66
- }.compare_by_identity
67
-
68
- @cached_visible_arguments = Hash.new do |h, arg|
69
- h[arg] = if @cached_visible[arg] && (arg_type = arg.type.unwrap) && @cached_visible[arg_type]
70
- add_type(arg_type, arg)
71
- true
72
- else
73
- false
74
- end
75
- end.compare_by_identity
76
-
77
- @cached_parent_fields = Hash.new do |h, type|
78
- h[type] = Hash.new do |h2, field_name|
79
- h2[field_name] = type.get_field(field_name, @context)
80
- end
81
- end.compare_by_identity
82
-
83
- @cached_parent_arguments = Hash.new do |h, arg_owner|
84
- h[arg_owner] = Hash.new do |h2, arg_name|
85
- h2[arg_name] = arg_owner.get_argument(arg_name, @context)
86
- end
87
- end.compare_by_identity
88
-
89
- @cached_possible_types = Hash.new do |h, type|
90
- h[type] = case type.kind.name
91
- when "INTERFACE"
92
- load_all_types
93
- pts = []
94
- @unfiltered_interface_type_memberships[type].each { |itm|
95
- if @cached_visible[itm] && (ot = itm.object_type) && @cached_visible[ot] && referenced?(ot)
96
- pts << ot
97
- end
98
- }
99
- pts
100
- when "UNION"
101
- pts = []
102
- type.type_memberships.each { |tm|
103
- if @cached_visible[tm] &&
104
- (ot = tm.object_type) &&
105
- @cached_visible[ot] &&
106
- referenced?(ot)
107
- pts << ot
108
- end
109
- }
110
- pts
111
- when "OBJECT"
112
- load_all_types
113
- if @all_types[type.graphql_name] == type
114
- [type]
115
- else
116
- EmptyObjects::EMPTY_ARRAY
117
- end
118
- else
119
- GraphQL::EmptyObjects::EMPTY_ARRAY
120
- end
121
- end.compare_by_identity
122
-
123
- @cached_enum_values = Hash.new do |h, enum_t|
124
- values = non_duplicate_items(enum_t.all_enum_value_definitions, @cached_visible)
125
- if values.size == 0
126
- raise GraphQL::Schema::Enum::MissingValuesError.new(enum_t)
127
- end
128
- h[enum_t] = values
129
- end.compare_by_identity
130
-
131
- @cached_fields = Hash.new do |h, owner|
132
- h[owner] = non_duplicate_items(owner.all_field_definitions.each(&:ensure_loaded), @cached_visible_fields[owner])
133
- end.compare_by_identity
134
-
135
- @cached_arguments = Hash.new do |h, owner|
136
- h[owner] = non_duplicate_items(owner.all_argument_definitions, @cached_visible_arguments)
137
- end.compare_by_identity
138
- end
139
-
140
- def field_on_visible_interface?(field, owner)
141
- ints = owner.interface_type_memberships.map(&:abstract_type)
142
- field_name = field.graphql_name
143
- filtered_ints = interfaces(owner)
144
- any_interface_has_field = false
145
- any_interface_has_visible_field = false
146
- ints.each do |int_t|
147
- if (_int_f_defn = @cached_parent_fields[int_t][field_name])
148
- any_interface_has_field = true
149
-
150
- if filtered_ints.include?(int_t) # TODO cycles, or maybe not necessary since previously checked? && @cached_visible_fields[owner][field]
151
- any_interface_has_visible_field = true
152
- break
153
- end
154
- end
155
- end
156
-
157
- if any_interface_has_field
158
- any_interface_has_visible_field
159
- else
160
- true
161
- end
162
- end
163
-
164
- def type(type_name)
165
- t = if (loaded_t = @all_types[type_name])
166
- loaded_t
167
- elsif !@all_types_loaded
168
- load_all_types
169
- @all_types[type_name]
170
- end
171
- if t
172
- if t.is_a?(Array)
173
- vis_t = nil
174
- t.each do |t_defn|
175
- if @cached_visible[t_defn]
176
- if vis_t.nil?
177
- vis_t = t_defn
178
- else
179
- raise_duplicate_definition(vis_t, t_defn)
180
- end
181
- end
182
- end
183
- vis_t
184
- else
185
- if t && @cached_visible[t]
186
- t
187
- else
188
- nil
189
- end
190
- end
191
- end
192
- end
193
-
194
- def field(owner, field_name)
195
- f = if owner.kind.fields? && (field = @cached_parent_fields[owner][field_name])
196
- field
197
- elsif owner == query_root && (entry_point_field = @schema.introspection_system.entry_point(name: field_name))
198
- entry_point_field
199
- elsif (dynamic_field = @schema.introspection_system.dynamic_field(name: field_name))
200
- dynamic_field
201
- else
202
- nil
203
- end
204
- if f.is_a?(Array)
205
- visible_f = nil
206
- f.each do |f_defn|
207
- if @cached_visible_fields[owner][f_defn]
208
-
209
- if visible_f.nil?
210
- visible_f = f_defn
211
- else
212
- raise_duplicate_definition(visible_f, f_defn)
213
- end
214
- end
215
- end
216
- visible_f.ensure_loaded
217
- elsif f && @cached_visible_fields[owner][f.ensure_loaded]
218
- f
219
- else
220
- nil
221
- end
222
- end
223
-
224
- def fields(owner)
225
- @cached_fields[owner]
226
- end
227
-
228
- def arguments(owner)
229
- @cached_arguments[owner]
230
- end
231
-
232
- def argument(owner, arg_name)
233
- arg = @cached_parent_arguments[owner][arg_name]
234
- if arg.is_a?(Array)
235
- visible_arg = nil
236
- arg.each do |arg_defn|
237
- if @cached_visible_arguments[arg_defn]
238
- if visible_arg.nil?
239
- visible_arg = arg_defn
240
- else
241
- raise_duplicate_definition(visible_arg, arg_defn)
242
- end
243
- end
244
- end
245
- visible_arg
246
- else
247
- if arg && @cached_visible_arguments[arg]
248
- arg
249
- else
250
- nil
251
- end
252
- end
253
- end
254
-
255
- def possible_types(type)
256
- @cached_possible_types[type]
257
- end
258
-
259
- def interfaces(obj_or_int_type)
260
- ints = obj_or_int_type.interface_type_memberships
261
- .select { |itm| @cached_visible[itm] && @cached_visible[itm.abstract_type] }
262
- .map!(&:abstract_type)
263
- ints.uniq! # Remove any duplicate interfaces implemented via other interfaces
264
- ints
265
- end
266
-
267
- def query_root
268
- add_if_visible(@schema.query)
269
- end
270
-
271
- def mutation_root
272
- add_if_visible(@schema.mutation)
273
- end
274
-
275
- def subscription_root
276
- add_if_visible(@schema.subscription)
277
- end
278
-
279
- def all_types
280
- load_all_types
281
- @all_types.values
282
- end
283
-
284
- def all_types_h
285
- load_all_types
286
- @all_types
287
- end
288
-
289
- def enum_values(owner)
290
- @cached_enum_values[owner]
291
- end
292
-
293
- def directive_exists?(dir_name)
294
- if (dir = @schema.directives[dir_name]) && @cached_visible[dir]
295
- !!dir
296
- else
297
- load_all_types
298
- !!@cached_directives[dir_name]
299
- end
300
- end
301
-
302
- def directives
303
- @all_directives ||= begin
304
- load_all_types
305
- dirs = []
306
- @schema.directives.each do |name, dir_defn|
307
- if !@cached_directives[name] && @cached_visible[dir_defn]
308
- dirs << dir_defn
309
- end
310
- end
311
- dirs.concat(@cached_directives.values)
312
- end
313
- end
314
-
315
- def loadable?(t, _ctx)
316
- !@all_types[t.graphql_name] && @cached_visible[t]
317
- end
318
-
319
- def loaded_types
320
- @all_types.values
321
- end
322
-
323
- def reachable_type?(name)
324
- load_all_types
325
- !!@all_types[name]
326
- end
327
-
328
- private
329
-
330
- def add_if_visible(t)
331
- (t && @cached_visible[t]) ? (add_type(t, true); t) : nil
332
- end
333
-
334
- def add_type(t, by_member)
335
- if t && @cached_visible[t]
336
- n = t.graphql_name
337
- if (prev_t = @all_types[n])
338
- if !prev_t.equal?(t)
339
- raise_duplicate_definition(prev_t, t)
340
- end
341
- false
342
- else
343
- @referenced_types[t] << by_member
344
- @all_types[n] = t
345
- @unvisited_types << t
346
- true
347
- end
348
- else
349
- false
350
- end
351
- end
352
-
353
- def non_duplicate_items(definitions, visibility_cache)
354
- non_dups = []
355
- definitions.each do |defn|
356
- if visibility_cache[defn]
357
- if (dup_defn = non_dups.find { |d| d.graphql_name == defn.graphql_name })
358
- raise_duplicate_definition(dup_defn, defn)
359
- end
360
- non_dups << defn
361
- end
362
- end
363
- non_dups
364
- end
365
-
366
- def raise_duplicate_definition(first_defn, second_defn)
367
- raise DuplicateNamesError.new(duplicated_name: first_defn.path, duplicated_definition_1: first_defn.inspect, duplicated_definition_2: second_defn.inspect)
368
- end
369
-
370
- def referenced?(t)
371
- load_all_types
372
- @referenced_types[t].any? { |reference| (reference == true) || @cached_visible[reference] }
373
- end
374
-
375
- def load_all_types
376
- return if @all_types_loaded
377
- @all_types_loaded = true
378
- entry_point_types = [
379
- query_root,
380
- mutation_root,
381
- subscription_root,
382
- *@schema.introspection_system.types.values,
383
- ]
384
-
385
- # Don't include any orphan_types whose interfaces aren't visible.
386
- @schema.orphan_types.each do |orphan_type|
387
- if @cached_visible[orphan_type] &&
388
- orphan_type.interface_type_memberships.any? { |tm| @cached_visible[tm] && @cached_visible[tm.abstract_type] }
389
- entry_point_types << orphan_type
390
- end
391
- end
392
-
393
- @schema.directives.each do |_dir_name, dir_class|
394
- if @cached_visible[dir_class]
395
- arguments(dir_class).each do |arg|
396
- entry_point_types << arg.type.unwrap
397
- end
398
- end
399
- end
400
-
401
- entry_point_types.compact! # TODO why is this necessary?!
402
- entry_point_types.flatten! # handle multiple defns
403
- entry_point_types.each { |t| add_type(t, true) }
404
-
405
- @unfiltered_interface_type_memberships = Hash.new { |h, k| h[k] = [] }.compare_by_identity
406
- @add_possible_types = Set.new
407
-
408
- while @unvisited_types.any?
409
- while t = @unvisited_types.pop
410
- # These have already been checked for `.visible?`
411
- visit_type(t)
412
- end
413
- @add_possible_types.each do |int_t|
414
- itms = @unfiltered_interface_type_memberships[int_t]
415
- itms.each do |itm|
416
- if @cached_visible[itm] && (obj_type = itm.object_type) && @cached_visible[obj_type]
417
- add_type(obj_type, itm)
418
- end
419
- end
420
- end
421
- @add_possible_types.clear
422
- end
423
-
424
- @all_types.delete_if { |type_name, type_defn| !referenced?(type_defn) }
425
- nil
426
- end
427
-
428
- def visit_type(type)
429
- visit_directives(type)
430
- case type.kind.name
431
- when "OBJECT", "INTERFACE"
432
- if type.kind.object?
433
- type.interface_type_memberships.each do |itm|
434
- @unfiltered_interface_type_memberships[itm.abstract_type] << itm
435
- end
436
- # recurse into visible implemented interfaces
437
- interfaces(type).each do |interface|
438
- add_type(interface, type)
439
- end
440
- else
441
- type.orphan_types.each { |t| add_type(t, type)}
442
- end
443
-
444
- # recurse into visible fields
445
- t_f = type.all_field_definitions
446
- t_f.each do |field|
447
- field.ensure_loaded
448
- if @cached_visible[field]
449
- visit_directives(field)
450
- field_type = field.type.unwrap
451
- if field_type.kind.interface?
452
- @add_possible_types.add(field_type)
453
- end
454
- add_type(field_type, field)
455
-
456
- # recurse into visible arguments
457
- arguments(field).each do |argument|
458
- visit_directives(argument)
459
- add_type(argument.type.unwrap, argument)
460
- end
461
- end
462
- end
463
- when "INPUT_OBJECT"
464
- # recurse into visible arguments
465
- arguments(type).each do |argument|
466
- visit_directives(argument)
467
- add_type(argument.type.unwrap, argument)
468
- end
469
- when "UNION"
470
- # recurse into visible possible types
471
- type.type_memberships.each do |tm|
472
- if @cached_visible[tm]
473
- obj_t = tm.object_type
474
- if obj_t.is_a?(String)
475
- obj_t = Member::BuildType.constantize(obj_t)
476
- tm.object_type = obj_t
477
- end
478
- if @cached_visible[obj_t]
479
- add_type(obj_t, tm)
480
- end
481
- end
482
- end
483
- when "ENUM"
484
- enum_values(type).each do |val|
485
- visit_directives(val)
486
- end
487
- when "SCALAR"
488
- # pass
489
- end
490
- end
491
-
492
- def visit_directives(member)
493
- member.directives.each { |dir|
494
- dir_class = dir.class
495
- if @cached_visible[dir_class]
496
- dir_name = dir_class.graphql_name
497
- if (existing_dir = @cached_directives[dir_name])
498
- if existing_dir != dir_class
499
- raise ArgumentError, "Two directives for `@#{dir_name}`: #{existing_dir}, #{dir.class}"
500
- end
501
- else
502
- @cached_directives[dir.graphql_name] = dir_class
503
- end
504
- end
505
- }
506
- end
507
- end
508
- end
509
- end