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.
- checksums.yaml +4 -4
- data/lib/generators/graphql/core.rb +47 -0
- data/lib/generators/graphql/install_generator.rb +15 -20
- data/lib/generators/graphql/mutation_generator.rb +31 -1
- data/lib/generators/graphql/templates/mutation.erb +2 -2
- data/lib/generators/graphql/templates/mutation_type.erb +5 -0
- data/lib/generators/graphql/templates/schema.erb +0 -1
- data/lib/graphql/argument.rb +6 -5
- data/lib/graphql/backwards_compatibility.rb +18 -4
- data/lib/graphql/base_type.rb +1 -1
- data/lib/graphql/compatibility/execution_specification/counter_schema.rb +1 -1
- data/lib/graphql/compatibility/execution_specification/specification_schema.rb +1 -1
- data/lib/graphql/compatibility/lazy_execution_specification.rb +9 -2
- data/lib/graphql/define.rb +1 -0
- data/lib/graphql/define/defined_object_proxy.rb +1 -1
- data/lib/graphql/define/no_definition_error.rb +7 -0
- data/lib/graphql/enum_type.rb +4 -0
- data/lib/graphql/execution/execute.rb +3 -3
- data/lib/graphql/execution/field_result.rb +1 -1
- data/lib/graphql/execution/lazy/resolve.rb +10 -9
- data/lib/graphql/execution/multiplex.rb +6 -5
- data/lib/graphql/input_object_type.rb +5 -1
- data/lib/graphql/interface_type.rb +12 -3
- data/lib/graphql/query.rb +21 -5
- data/lib/graphql/query/context.rb +11 -0
- data/lib/graphql/schema.rb +48 -27
- data/lib/graphql/schema/build_from_definition.rb +1 -1
- data/lib/graphql/schema/build_from_definition/resolve_map.rb +2 -2
- data/lib/graphql/schema/loader.rb +1 -1
- data/lib/graphql/schema/traversal.rb +91 -0
- data/lib/graphql/schema/validation.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +41 -7
- data/lib/graphql/union_type.rb +13 -2
- data/lib/graphql/version.rb +1 -1
- data/readme.md +1 -3
- data/spec/generators/graphql/install_generator_spec.rb +3 -1
- data/spec/generators/graphql/mutation_generator_spec.rb +14 -0
- data/spec/graphql/analysis/max_query_complexity_spec.rb +12 -1
- data/spec/graphql/analysis/query_complexity_spec.rb +1 -1
- data/spec/graphql/argument_spec.rb +29 -0
- data/spec/graphql/define/assign_argument_spec.rb +4 -4
- data/spec/graphql/define/instance_definable_spec.rb +1 -1
- data/spec/graphql/enum_type_spec.rb +8 -0
- data/spec/graphql/execution/lazy_spec.rb +30 -3
- data/spec/graphql/interface_type_spec.rb +44 -0
- data/spec/graphql/introspection/schema_type_spec.rb +3 -0
- data/spec/graphql/introspection/type_type_spec.rb +1 -0
- data/spec/graphql/object_type_spec.rb +8 -3
- data/spec/graphql/query/context_spec.rb +18 -0
- data/spec/graphql/query/executor_spec.rb +1 -1
- data/spec/graphql/query/literal_input_spec.rb +31 -15
- data/spec/graphql/query/serial_execution/value_resolution_spec.rb +1 -1
- data/spec/graphql/query/variables_spec.rb +25 -1
- data/spec/graphql/query_spec.rb +24 -9
- data/spec/graphql/relay/mutation_spec.rb +1 -1
- data/spec/graphql/schema/build_from_definition_spec.rb +1 -1
- data/spec/graphql/schema/loader_spec.rb +1 -1
- data/spec/graphql/schema/printer_spec.rb +1 -1
- data/spec/graphql/schema/{reduce_types_spec.rb → traversal_spec.rb} +21 -4
- data/spec/graphql/schema/warden_spec.rb +1 -1
- data/spec/graphql/schema_spec.rb +23 -2
- data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +133 -0
- data/spec/graphql/union_type_spec.rb +53 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/support/dummy/data.rb +14 -5
- data/spec/support/dummy/schema.rb +46 -5
- data/spec/support/star_wars/data.rb +10 -6
- data/spec/support/star_wars/schema.rb +5 -2
- metadata +8 -7
- data/lib/graphql/schema/instrumented_field_map.rb +0 -40
- data/lib/graphql/schema/reduce_types.rb +0 -69
- 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
|
|
data/spec/support/dummy/data.rb
CHANGED
@@ -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
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
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:
|
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
|
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
|
+
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-
|
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
|