graphql 1.6.4 → 1.6.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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/core.rb +47 -0
  3. data/lib/generators/graphql/install_generator.rb +15 -20
  4. data/lib/generators/graphql/mutation_generator.rb +31 -1
  5. data/lib/generators/graphql/templates/mutation.erb +2 -2
  6. data/lib/generators/graphql/templates/mutation_type.erb +5 -0
  7. data/lib/generators/graphql/templates/schema.erb +0 -1
  8. data/lib/graphql/argument.rb +6 -5
  9. data/lib/graphql/backwards_compatibility.rb +18 -4
  10. data/lib/graphql/base_type.rb +1 -1
  11. data/lib/graphql/compatibility/execution_specification/counter_schema.rb +1 -1
  12. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +1 -1
  13. data/lib/graphql/compatibility/lazy_execution_specification.rb +9 -2
  14. data/lib/graphql/define.rb +1 -0
  15. data/lib/graphql/define/defined_object_proxy.rb +1 -1
  16. data/lib/graphql/define/no_definition_error.rb +7 -0
  17. data/lib/graphql/enum_type.rb +4 -0
  18. data/lib/graphql/execution/execute.rb +3 -3
  19. data/lib/graphql/execution/field_result.rb +1 -1
  20. data/lib/graphql/execution/lazy/resolve.rb +10 -9
  21. data/lib/graphql/execution/multiplex.rb +6 -5
  22. data/lib/graphql/input_object_type.rb +5 -1
  23. data/lib/graphql/interface_type.rb +12 -3
  24. data/lib/graphql/query.rb +21 -5
  25. data/lib/graphql/query/context.rb +11 -0
  26. data/lib/graphql/schema.rb +48 -27
  27. data/lib/graphql/schema/build_from_definition.rb +1 -1
  28. data/lib/graphql/schema/build_from_definition/resolve_map.rb +2 -2
  29. data/lib/graphql/schema/loader.rb +1 -1
  30. data/lib/graphql/schema/traversal.rb +91 -0
  31. data/lib/graphql/schema/validation.rb +1 -1
  32. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +41 -7
  33. data/lib/graphql/union_type.rb +13 -2
  34. data/lib/graphql/version.rb +1 -1
  35. data/readme.md +1 -3
  36. data/spec/generators/graphql/install_generator_spec.rb +3 -1
  37. data/spec/generators/graphql/mutation_generator_spec.rb +14 -0
  38. data/spec/graphql/analysis/max_query_complexity_spec.rb +12 -1
  39. data/spec/graphql/analysis/query_complexity_spec.rb +1 -1
  40. data/spec/graphql/argument_spec.rb +29 -0
  41. data/spec/graphql/define/assign_argument_spec.rb +4 -4
  42. data/spec/graphql/define/instance_definable_spec.rb +1 -1
  43. data/spec/graphql/enum_type_spec.rb +8 -0
  44. data/spec/graphql/execution/lazy_spec.rb +30 -3
  45. data/spec/graphql/interface_type_spec.rb +44 -0
  46. data/spec/graphql/introspection/schema_type_spec.rb +3 -0
  47. data/spec/graphql/introspection/type_type_spec.rb +1 -0
  48. data/spec/graphql/object_type_spec.rb +8 -3
  49. data/spec/graphql/query/context_spec.rb +18 -0
  50. data/spec/graphql/query/executor_spec.rb +1 -1
  51. data/spec/graphql/query/literal_input_spec.rb +31 -15
  52. data/spec/graphql/query/serial_execution/value_resolution_spec.rb +1 -1
  53. data/spec/graphql/query/variables_spec.rb +25 -1
  54. data/spec/graphql/query_spec.rb +24 -9
  55. data/spec/graphql/relay/mutation_spec.rb +1 -1
  56. data/spec/graphql/schema/build_from_definition_spec.rb +1 -1
  57. data/spec/graphql/schema/loader_spec.rb +1 -1
  58. data/spec/graphql/schema/printer_spec.rb +1 -1
  59. data/spec/graphql/schema/{reduce_types_spec.rb → traversal_spec.rb} +21 -4
  60. data/spec/graphql/schema/warden_spec.rb +1 -1
  61. data/spec/graphql/schema_spec.rb +23 -2
  62. data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +133 -0
  63. data/spec/graphql/union_type_spec.rb +53 -0
  64. data/spec/spec_helper.rb +9 -0
  65. data/spec/support/dummy/data.rb +14 -5
  66. data/spec/support/dummy/schema.rb +46 -5
  67. data/spec/support/star_wars/data.rb +10 -6
  68. data/spec/support/star_wars/schema.rb +5 -2
  69. metadata +8 -7
  70. data/lib/graphql/schema/instrumented_field_map.rb +0 -40
  71. data/lib/graphql/schema/reduce_types.rb +0 -69
  72. data/lib/graphql/schema/type_map.rb +0 -31
@@ -26,6 +26,59 @@ describe GraphQL::UnionType do
26
26
  assert_equal(false, union.include?(type_3))
27
27
  end
28
28
 
29
+ it '#resolve_type raises error if resolved type is not in possible_types' do
30
+ test_str = 'Hello world'
31
+ union.resolve_type = ->(value, ctx) {
32
+ "This is not the types you are looking for"
33
+ }
34
+ fake_ctx = OpenStruct.new(query: GraphQL::Query.new(Dummy::Schema, ""))
35
+
36
+ assert_raises(RuntimeError) {
37
+ union.resolve_type(test_str, fake_ctx)
38
+ }
39
+ end
40
+
41
+ describe "#resolve_type" do
42
+ let(:result) { Dummy::Schema.execute(query_string) }
43
+ let(:query_string) {%|
44
+ {
45
+ allAnimal {
46
+ type: __typename
47
+ ... on Cow {
48
+ cowName: name
49
+ }
50
+ ... on Goat {
51
+ goatName: name
52
+ }
53
+ }
54
+
55
+ allAnimalAsCow {
56
+ type: __typename
57
+ ... on Cow {
58
+ name
59
+ }
60
+ }
61
+ }
62
+ |}
63
+
64
+ it 'returns correct types for general schema and specific union' do
65
+ expected_result = {
66
+ # When using Query#resolve_type
67
+ "allAnimal" => [
68
+ { "type" => "Cow", "cowName" => "Billy" },
69
+ { "type" => "Goat", "goatName" => "Gilly" }
70
+ ],
71
+
72
+ # When using UnionType#resolve_type
73
+ "allAnimalAsCow" => [
74
+ { "type" => "Cow", "name" => "Billy" },
75
+ { "type" => "Cow", "name" => "Gilly" }
76
+ ]
77
+ }
78
+ assert_equal expected_result, result["data"]
79
+ end
80
+ end
81
+
29
82
  describe "typecasting from union to union" do
30
83
  let(:result) { Dummy::Schema.execute(query_string) }
31
84
  let(:query_string) {%|
data/spec/spec_helper.rb CHANGED
@@ -6,10 +6,12 @@ require "rails/all"
6
6
  require "rails/generators"
7
7
  require "jdbc/sqlite3" if RUBY_ENGINE == 'jruby'
8
8
  require "sqlite3" if RUBY_ENGINE == 'ruby'
9
+ require "pg" if RUBY_ENGINE == 'ruby'
9
10
  require "sequel"
10
11
  require "graphql"
11
12
  require "graphql/rake_task"
12
13
  require "benchmark"
14
+ require "pry"
13
15
  require "minitest/autorun"
14
16
  require "minitest/focus"
15
17
  require "minitest/reporters"
@@ -24,9 +26,11 @@ Minitest.backtrace_filter = Minitest::BacktraceFilter.new
24
26
 
25
27
  # This is for convenient access to metadata in test definitions
26
28
  assign_metadata_key = ->(target, key, value) { target.metadata[key] = value }
29
+ assign_metadata_flag = ->(target, flag) { target.metadata[flag] = true }
27
30
  GraphQL::BaseType.accepts_definitions(metadata: assign_metadata_key)
28
31
  GraphQL::Field.accepts_definitions(metadata: assign_metadata_key)
29
32
  GraphQL::Argument.accepts_definitions(metadata: assign_metadata_key)
33
+ GraphQL::Argument.accepts_definitions(metadata_flag: assign_metadata_flag)
30
34
  GraphQL::EnumType::EnumValue.accepts_definitions(metadata: assign_metadata_key)
31
35
 
32
36
  # Can be used as a GraphQL::Schema::Warden for some purposes, but allows nothing
@@ -36,6 +40,11 @@ module NothingWarden
36
40
  end
37
41
  end
38
42
 
43
+ # Use this when a schema requires a `resolve_type` hook
44
+ # but you know it won't be called
45
+ NO_OP_RESOLVE_TYPE = ->(type, obj, ctx) {
46
+ raise "this should never be called"
47
+ }
39
48
  # Load support files
40
49
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
41
50
 
@@ -6,6 +6,11 @@ module Dummy
6
6
  # This is buggy on purpose -- it shouldn't be called during execution.
7
7
  other.id == id
8
8
  end
9
+
10
+ # Alias for when this is treated as milk in EdibleAsMilkInterface
11
+ def fatContent # rubocop:disable Style/MethodName
12
+ fat_content
13
+ end
9
14
  end
10
15
 
11
16
  CHEESES = {
@@ -25,9 +30,13 @@ module Dummy
25
30
  milks: [MILKS[1]]
26
31
  )
27
32
 
28
- COW = OpenStruct.new(
29
- id: 1,
30
- name: "Billy",
31
- last_produced_dairy: MILKS[1]
32
- )
33
+ Cow = Struct.new(:id, :name, :last_produced_dairy)
34
+ COWS = {
35
+ 1 => Cow.new(1, "Billy", MILKS[1])
36
+ }
37
+
38
+ Goat = Struct.new(:id, :name, :last_produced_dairy)
39
+ GOATS = {
40
+ 1 => Goat.new(1, "Gilly", MILKS[1]),
41
+ }
33
42
  end
@@ -21,6 +21,12 @@ module Dummy
21
21
  field :selfAsEdible, EdibleInterface, resolve: ->(o, a, c) { o }
22
22
  end
23
23
 
24
+ EdibleAsMilkInterface = EdibleInterface.redefine do
25
+ name "EdibleAsMilk"
26
+ description "Milk :+1:"
27
+ resolve_type ->(obj, ctx) { MilkType }
28
+ end
29
+
24
30
  AnimalProductInterface = GraphQL::InterfaceType.define do
25
31
  name "AnimalProduct"
26
32
  description "Comes from an animal, no joke"
@@ -48,7 +54,7 @@ module Dummy
48
54
  name "Cheese"
49
55
  class_names ["Cheese"]
50
56
  description "Cultured dairy product"
51
- interfaces [EdibleInterface, AnimalProductInterface, LocalProductInterface]
57
+ interfaces [EdibleInterface, EdibleAsMilkInterface, AnimalProductInterface, LocalProductInterface]
52
58
 
53
59
  # Can have (name, type, desc)
54
60
  field :id, !types.Int, "Unique identifier"
@@ -96,7 +102,7 @@ module Dummy
96
102
  MilkType = GraphQL::ObjectType.define do
97
103
  name "Milk"
98
104
  description "Dairy beverage"
99
- interfaces [EdibleInterface, AnimalProductInterface, LocalProductInterface]
105
+ interfaces [EdibleInterface, EdibleAsMilkInterface, AnimalProductInterface, LocalProductInterface]
100
106
  field :id, !types.ID
101
107
  field :source, !DairyAnimalEnum, "Animal which produced this milk", hash_key: :source
102
108
  field :origin, !types.String, "Place the milk comes from"
@@ -152,7 +158,7 @@ module Dummy
152
158
 
153
159
  CowType = GraphQL::ObjectType.define do
154
160
  name "Cow"
155
- description "A farm where milk is harvested and cheese is produced"
161
+ description "A bovine animal that produces milk"
156
162
  field :id, !types.ID
157
163
  field :name, types.String
158
164
  field :last_produced_dairy, DairyProductUnion
@@ -168,6 +174,29 @@ module Dummy
168
174
  end
169
175
  end
170
176
 
177
+ GoatType = GraphQL::ObjectType.define do
178
+ name "Goat"
179
+ description "An caprinae animal that produces milk"
180
+ field :id, !types.ID
181
+ field :name, types.String
182
+ field :last_produced_dairy, DairyProductUnion
183
+ end
184
+
185
+ AnimalUnion = GraphQL::UnionType.define do
186
+ name "Animal"
187
+ description "Species of living things"
188
+ possible_types [CowType, GoatType]
189
+ end
190
+
191
+ AnimalAsCowUnion = GraphQL::UnionType.define do
192
+ name "AnimalAsCow"
193
+ description "All animals go mooooo!"
194
+ possible_types [CowType]
195
+ resolve_type ->(obj, ctx) {
196
+ CowType
197
+ }
198
+ end
199
+
171
200
  ResourceOrderType = GraphQL::InputObjectType.define {
172
201
  name "ResourceOrderType"
173
202
  description "Properties used to determine ordering"
@@ -271,7 +300,7 @@ module Dummy
271
300
  field :dairy, function: GetSingleton.new(type: DairyType, data: DAIRY)
272
301
  field :fromSource, &SourceFieldDefn
273
302
  field :favoriteEdible, FavoriteFieldDefn
274
- field :cow, function: GetSingleton.new(type: CowType, data: COW)
303
+ field :cow, function: GetSingleton.new(type: CowType, data: COWS[1])
275
304
  field :searchDairy do
276
305
  description "Find dairy products matching a description"
277
306
  type !DairyProductUnion
@@ -287,6 +316,14 @@ module Dummy
287
316
  }
288
317
  end
289
318
 
319
+ field :allAnimal, !types[AnimalUnion] do
320
+ resolve ->(obj, args, ctx) { COWS.values + GOATS.values }
321
+ end
322
+
323
+ field :allAnimalAsCow, !types[AnimalAsCowUnion] do
324
+ resolve ->(obj, args, ctx) { COWS.values + GOATS.values }
325
+ end
326
+
290
327
  field :allDairy, types[DairyProductUnion] do
291
328
  argument :executionErrorAtIndex, types.Int
292
329
  resolve ->(obj, args, ctx) {
@@ -300,6 +337,10 @@ module Dummy
300
337
  resolve ->(obj, args, ctx) { CHEESES.values + MILKS.values }
301
338
  end
302
339
 
340
+ field :allEdibleAsMilk, types[EdibleAsMilkInterface] do
341
+ resolve ->(obj, args, ctx) { CHEESES.values + MILKS.values }
342
+ end
343
+
303
344
  field :error do
304
345
  description "Raise an error"
305
346
  type GraphQL::STRING_TYPE
@@ -375,7 +416,7 @@ module Dummy
375
416
 
376
417
  rescue_from(NoSuchDairyError) { |err| err.message }
377
418
 
378
- resolve_type ->(obj, ctx) {
419
+ resolve_type ->(type, obj, ctx) {
379
420
  Schema.types[obj.class.name.split("::").last]
380
421
  }
381
422
  end
@@ -21,10 +21,20 @@ module StarWars
21
21
  # ActiveRecord::Base.logger = Logger.new(STDOUT)
22
22
  `rm -f ./_test_.db`
23
23
  # Set up "Bases" in ActiveRecord
24
+
24
25
  if jruby?
25
26
  ActiveRecord::Base.establish_connection(adapter: "jdbcsqlite3", database: "./_test_.db")
27
+ Sequel.connect('jdbc:sqlite:./_test_.db')
28
+ elsif ENV['DATABASE'] == 'POSTGRESQL'
29
+ ActiveRecord::Base.establish_connection(
30
+ adapter: "postgresql",
31
+ username: "postgres",
32
+ database: "graphql_ruby_test"
33
+ )
34
+ DB = Sequel.connect('postgres://postgres:@localhost:5432/graphql_ruby_test')
26
35
  else
27
36
  ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: "./_test_.db")
37
+ DB = Sequel.sqlite("./_test_.db")
28
38
  end
29
39
 
30
40
  ActiveRecord::Schema.define do
@@ -46,12 +56,6 @@ module StarWars
46
56
  Base.create!(name: "Shield Generator", planet: "Endor", faction_id: 2)
47
57
  Base.create!(name: "Headquarters", planet: "Coruscant", faction_id: 2)
48
58
 
49
- # Also, set up Bases with Sequel
50
- DB = if jruby?
51
- Sequel.connect('jdbc:sqlite:./_test_.db')
52
- else
53
- Sequel.sqlite("./_test_.db")
54
- end
55
59
  class SequelBase < Sequel::Model(:bases)
56
60
  end
57
61
 
@@ -304,7 +304,10 @@ module StarWars
304
304
 
305
305
  connection :newestBasesGroupedByFaction, BaseType.connection_type do
306
306
  resolve ->(obj, args, ctx) {
307
- Base.order('sum(faction_id) desc').group(:faction_id)
307
+ Base
308
+ .having('id in (select max(id) from bases group by faction_id)')
309
+ .group(:id)
310
+ .order('faction_id desc')
308
311
  }
309
312
  end
310
313
 
@@ -359,7 +362,7 @@ module StarWars
359
362
  mutation(MutationType)
360
363
  default_max_page_size 3
361
364
 
362
- resolve_type ->(object, ctx) {
365
+ resolve_type ->(type, object, ctx) {
363
366
  if object == :test_error
364
367
  :not_a_type
365
368
  elsif object.is_a?(Base)
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: 1.6.4
4
+ version: 1.6.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-20 00:00:00.000000000 Z
11
+ date: 2017-07-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: benchmark-ips
@@ -299,6 +299,7 @@ extra_rdoc_files: []
299
299
  files:
300
300
  - ".yardopts"
301
301
  - MIT-LICENSE
302
+ - lib/generators/graphql/core.rb
302
303
  - lib/generators/graphql/enum_generator.rb
303
304
  - lib/generators/graphql/function_generator.rb
304
305
  - lib/generators/graphql/install_generator.rb
@@ -312,6 +313,7 @@ files:
312
313
  - lib/generators/graphql/templates/interface.erb
313
314
  - lib/generators/graphql/templates/loader.erb
314
315
  - lib/generators/graphql/templates/mutation.erb
316
+ - lib/generators/graphql/templates/mutation_type.erb
315
317
  - lib/generators/graphql/templates/object.erb
316
318
  - lib/generators/graphql/templates/query_type.erb
317
319
  - lib/generators/graphql/templates/schema.erb
@@ -351,6 +353,7 @@ files:
351
353
  - lib/graphql/define/assign_object_field.rb
352
354
  - lib/graphql/define/defined_object_proxy.rb
353
355
  - lib/graphql/define/instance_definable.rb
356
+ - lib/graphql/define/no_definition_error.rb
354
357
  - lib/graphql/define/non_null_with_bang.rb
355
358
  - lib/graphql/define/type_definer.rb
356
359
  - lib/graphql/directive.rb
@@ -465,18 +468,16 @@ files:
465
468
  - lib/graphql/schema/catchall_middleware.rb
466
469
  - lib/graphql/schema/default_parse_error.rb
467
470
  - lib/graphql/schema/default_type_error.rb
468
- - lib/graphql/schema/instrumented_field_map.rb
469
471
  - lib/graphql/schema/invalid_type_error.rb
470
472
  - lib/graphql/schema/loader.rb
471
473
  - lib/graphql/schema/middleware_chain.rb
472
474
  - lib/graphql/schema/null_mask.rb
473
475
  - lib/graphql/schema/possible_types.rb
474
476
  - lib/graphql/schema/printer.rb
475
- - lib/graphql/schema/reduce_types.rb
476
477
  - lib/graphql/schema/rescue_middleware.rb
477
478
  - lib/graphql/schema/timeout_middleware.rb
479
+ - lib/graphql/schema/traversal.rb
478
480
  - lib/graphql/schema/type_expression.rb
479
- - lib/graphql/schema/type_map.rb
480
481
  - lib/graphql/schema/unique_within_type.rb
481
482
  - lib/graphql/schema/validation.rb
482
483
  - lib/graphql/schema/warden.rb
@@ -600,9 +601,9 @@ files:
600
601
  - spec/graphql/schema/loader_spec.rb
601
602
  - spec/graphql/schema/middleware_chain_spec.rb
602
603
  - spec/graphql/schema/printer_spec.rb
603
- - spec/graphql/schema/reduce_types_spec.rb
604
604
  - spec/graphql/schema/rescue_middleware_spec.rb
605
605
  - spec/graphql/schema/timeout_middleware_spec.rb
606
+ - spec/graphql/schema/traversal_spec.rb
606
607
  - spec/graphql/schema/type_expression_spec.rb
607
608
  - spec/graphql/schema/unique_within_type_spec.rb
608
609
  - spec/graphql/schema/validation_spec.rb
@@ -750,9 +751,9 @@ test_files:
750
751
  - spec/graphql/schema/loader_spec.rb
751
752
  - spec/graphql/schema/middleware_chain_spec.rb
752
753
  - spec/graphql/schema/printer_spec.rb
753
- - spec/graphql/schema/reduce_types_spec.rb
754
754
  - spec/graphql/schema/rescue_middleware_spec.rb
755
755
  - spec/graphql/schema/timeout_middleware_spec.rb
756
+ - spec/graphql/schema/traversal_spec.rb
756
757
  - spec/graphql/schema/type_expression_spec.rb
757
758
  - spec/graphql/schema/unique_within_type_spec.rb
758
759
  - spec/graphql/schema/validation_spec.rb
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
- module GraphQL
3
- class Schema
4
- # A two-level map with fields as the last values.
5
- # The first level is type names, which point to a second map.
6
- # The second level is field names, which point to fields.
7
- #
8
- # The catch is, the fields in this map _may_ have been modified by being instrumented.
9
- class InstrumentedFieldMap
10
- # Build a map using types from `schema` and instrumenters in `field_instrumenters`
11
- # @param schema [GraphQL::Schema]
12
- # @param field_instrumenters [Array<#instrument(type, field)>]
13
- def initialize(schema, field_instrumenters)
14
- @storage = Hash.new { |h, k| h[k] = {} }
15
- schema.types.each do |type_name, type|
16
- if type.kind.fields?
17
- type.all_fields.each do |field_defn|
18
- instrumented_field_defn = field_instrumenters.reduce(field_defn) do |defn, inst|
19
- inst.instrument(type, defn)
20
- end
21
- self.set(type.name, field_defn.name, instrumented_field_defn)
22
- end
23
- end
24
- end
25
- end
26
-
27
- def set(type_name, field_name, field)
28
- @storage[type_name][field_name] = field
29
- end
30
-
31
- def get(type_name, field_name)
32
- @storage[type_name][field_name]
33
- end
34
-
35
- def get_all(type_name)
36
- @storage[type_name]
37
- end
38
- end
39
- end
40
- end
@@ -1,69 +0,0 @@
1
- # frozen_string_literal: true
2
- module GraphQL
3
- class Schema
4
- module ReduceTypes
5
- # @param types [Array<GraphQL::BaseType>] members of a schema to crawl for all member types
6
- # @return [GraphQL::Schema::TypeMap] `{name => Type}` pairs derived from `types`
7
- def self.reduce(types)
8
- type_map = GraphQL::Schema::TypeMap.new
9
- types.each do |type|
10
- reduce_type(type, type_map, type.name)
11
- end
12
- type_map
13
- end
14
-
15
- private
16
-
17
- # Based on `type`, add members to `type_hash`.
18
- # If `type` has already been visited, just return the `type_hash` as-is
19
- def self.reduce_type(type, type_hash, context_description)
20
- if !type.is_a?(GraphQL::BaseType)
21
- message = "#{context_description} has an invalid type: must be an instance of GraphQL::BaseType, not #{type.class.inspect} (#{type.inspect})"
22
- raise GraphQL::Schema::InvalidTypeError.new(message)
23
- end
24
-
25
- type = type.unwrap
26
-
27
- # Don't re-visit a type
28
- if !type_hash.fetch(type.name, nil).equal?(type)
29
- validate_type(type, context_description)
30
- type_hash[type.name] = type
31
- crawl_type(type, type_hash, context_description)
32
- end
33
- end
34
-
35
- def self.crawl_type(type, type_hash, context_description)
36
- if type.kind.fields?
37
- type.all_fields.each do |field|
38
- reduce_type(field.type, type_hash, "Field #{type.name}.#{field.name}")
39
- field.arguments.each do |name, argument|
40
- reduce_type(argument.type, type_hash, "Argument #{name} on #{type.name}.#{field.name}")
41
- end
42
- end
43
- end
44
- if type.kind.object?
45
- type.interfaces.each do |interface|
46
- reduce_type(interface, type_hash, "Interface on #{type.name}")
47
- end
48
- end
49
- if type.kind.union?
50
- type.possible_types.each do |possible_type|
51
- reduce_type(possible_type, type_hash, "Possible type for #{type.name}")
52
- end
53
- end
54
- if type.kind.input_object?
55
- type.arguments.each do |argument_name, argument|
56
- reduce_type(argument.type, type_hash, "Input field #{type.name}.#{argument_name}")
57
- end
58
- end
59
- end
60
-
61
- def self.validate_type(type, context_description)
62
- error_message = GraphQL::Schema::Validation.validate(type)
63
- if error_message
64
- raise GraphQL::Schema::InvalidTypeError.new("#{context_description} is invalid: #{error_message}")
65
- end
66
- end
67
- end
68
- end
69
- end