graphql 2.3.14 → 2.4.0

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.
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