graphql 0.12.0 → 0.12.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b779fe5af77f89213fae236cb0e7441bdfe4b0c1
4
- data.tar.gz: 457dc5cb4468a2c57f758162dc112db07e0801df
3
+ metadata.gz: 6682396f1618ee3660ec3120bf597c109d0e2752
4
+ data.tar.gz: 93a3813ff37f3eb9f4e447eda9aabd3db2688de3
5
5
  SHA512:
6
- metadata.gz: 1910cea7688e8ddd090ee5e7d64300a6ae39524e2ad5677a0552072ba4704a20213cbd25b9889900bcb2b610b6ff5aedfd9c2757614715aaf44ca4535a091ccd
7
- data.tar.gz: cfcbe1c03d9fd8b9ed510af1d64d24dacaf147b337d383eb7de6c596ed200f6a8c2b3c87deef8dfab3cdb7b421811d034a4516c3c6db0e3af089b94758d8cc16
6
+ metadata.gz: 09eb390035a47146f403a393c1695d7d6355a7d7573c70a277547113f2abad887cded1bb275fa7865c57df5631119487fdd3e50ddf859e705960fc0f67c8fe6e
7
+ data.tar.gz: d4bef1a775db4a7bd2d58a60c283bce67942ab41bfb551d3d1a7f8080ecdcfc2959d7c0f51872cb80016e77cca68bd04fbede2479217c4b994e6919fb68f86e8
@@ -18,11 +18,14 @@ class GraphQL::Schema
18
18
  # @param query [GraphQL::ObjectType] the query root for the schema
19
19
  # @param mutation [GraphQL::ObjectType] the mutation root for the schema
20
20
  # @param subscription [GraphQL::ObjectType] the subscription root for the schema
21
- def initialize(query:, mutation: nil, subscription: nil, max_depth: nil)
21
+ # @param max_depth [Integer] maximum query nesting (if it's greater, raise an error)
22
+ # @param types [Array<GraphQL::BaseType>] additional types to include in this schema
23
+ def initialize(query:, mutation: nil, subscription: nil, max_depth: nil, types: [])
22
24
  @query = query
23
25
  @mutation = mutation
24
26
  @subscription = subscription
25
27
  @max_depth = max_depth
28
+ @orphan_types = types
26
29
  @directives = DIRECTIVES.reduce({}) { |m, d| m[d.name] = d; m }
27
30
  @static_validator = GraphQL::StaticValidation::Validator.new(schema: self)
28
31
  @rescue_middleware = GraphQL::Schema::RescueMiddleware.new
@@ -37,7 +40,10 @@ class GraphQL::Schema
37
40
 
38
41
  # @return [GraphQL::Schema::TypeMap] `{ name => type }` pairs of types in this schema
39
42
  def types
40
- @types ||= TypeReducer.find_all([query, mutation, GraphQL::Introspection::SchemaType].compact)
43
+ @types ||= begin
44
+ all_types = @orphan_types + [query, mutation, GraphQL::Introspection::SchemaType]
45
+ TypeReducer.find_all(all_types.compact)
46
+ end
41
47
  end
42
48
 
43
49
  # Execute a query on itself.
@@ -8,10 +8,14 @@ module GraphQL
8
8
  # If you want a type, but want to handle the undefined case, use {#fetch}.
9
9
  class TypeMap
10
10
  extend Forwardable
11
- def_delegators :@storage, :key?, :keys, :values
11
+ def_delegators :@storage, :key?, :keys, :values, :fetch, :to_h
12
+
13
+ # Used for detecting deprecated interface member inferrance
14
+ attr_accessor :safely_discovered_types
12
15
 
13
16
  def initialize
14
17
  @storage = {}
18
+ @safely_discovered_types = []
15
19
  end
16
20
 
17
21
  def [](key)
@@ -26,8 +30,11 @@ module GraphQL
26
30
  end
27
31
  end
28
32
 
29
- def fetch(key, fallback_value)
30
- @storage.key?(key) ? @storage[key] : fallback_value
33
+ def warnings
34
+ interface_only_types = @storage.values - safely_discovered_types
35
+ interface_only_types.map do |unsafe_type|
36
+ "Type \"#{unsafe_type}\" was inferred from an interface's #possible_types. This won't be supported in the next version of GraphQL. Pass this type with the `types:` argument to `Schema.new` instead!"
37
+ end
31
38
  end
32
39
  end
33
40
  end
@@ -21,8 +21,13 @@ class GraphQL::Schema::TypeReducer
21
21
  def self.find_all(types)
22
22
  type_map = GraphQL::Schema::TypeMap.new
23
23
  types.reduce(type_map) do |memo, type|
24
- self.new(type, memo).result
24
+ type_map.safely_discovered_types << type
25
+ self.new(type.unwrap, memo).result
25
26
  end
27
+ type_map.warnings.each do |warning|
28
+ warn(warning)
29
+ end
30
+ type_map
26
31
  end
27
32
 
28
33
  private
@@ -34,22 +39,29 @@ class GraphQL::Schema::TypeReducer
34
39
  reduce_type(field.type, type_hash)
35
40
  field.arguments.each do |name, argument|
36
41
  reduce_type(argument.type, type_hash)
42
+ safely_discovered(type_hash, argument.type)
37
43
  end
44
+ safely_discovered(type_hash, field.type)
38
45
  end
39
46
  end
40
47
  if type.kind.object?
41
48
  type.interfaces.each do |interface|
42
49
  reduce_type(interface, type_hash)
50
+ safely_discovered(type_hash, interface)
43
51
  end
44
52
  end
45
53
  if type.kind.resolves?
46
54
  type.possible_types.each do |possible_type|
47
55
  reduce_type(possible_type, type_hash)
56
+ if type.kind.union?
57
+ safely_discovered(type_hash, possible_type)
58
+ end
48
59
  end
49
60
  end
50
61
  if type.kind.input_object?
51
62
  type.input_fields.each do |name, input_field|
52
63
  reduce_type(input_field.type, type_hash)
64
+ safely_discovered(type_hash, input_field.type)
53
65
  end
54
66
  end
55
67
 
@@ -72,4 +84,12 @@ class GraphQL::Schema::TypeReducer
72
84
  raise GraphQL::Schema::InvalidTypeError.new(type, errors)
73
85
  end
74
86
  end
87
+
88
+ def safely_discovered(type_hash, type)
89
+ inner_type = type.unwrap
90
+ if !type_hash.safely_discovered_types.include?(inner_type)
91
+
92
+ type_hash.safely_discovered_types << inner_type
93
+ end
94
+ end
75
95
  end
@@ -1,3 +1,3 @@
1
1
  module GraphQL
2
- VERSION = "0.12.0"
2
+ VERSION = "0.12.1"
3
3
  end
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe GraphQL::InterfaceType do
4
4
  let(:interface) { EdibleInterface }
5
5
  it 'has possible types' do
6
- assert_equal([CheeseType, MilkType], interface.possible_types)
6
+ assert_equal([CheeseType, MilkType, HoneyType], interface.possible_types)
7
7
  end
8
8
 
9
9
  it 'resolves types for objects' do
@@ -57,7 +57,7 @@ describe GraphQL::Introspection::TypeType do
57
57
  "animalProduct" => {
58
58
  "name"=>"AnimalProduct",
59
59
  "kind"=>"INTERFACE",
60
- "possibleTypes"=>[{"name"=>"Cheese"}, {"name"=>"Milk"}],
60
+ "possibleTypes"=>[{"name"=>"Cheese"}, {"name"=>"Milk"}, {"name"=>"Honey"}],
61
61
  "fields"=>[
62
62
  {"name"=>"source"},
63
63
  ]
@@ -1,8 +1,9 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe GraphQL::Schema::TypeReducer do
4
+ let(:type_map) { GraphQL::Schema::TypeMap.new }
4
5
  it 'finds types from a single type and its fields' do
5
- reducer = GraphQL::Schema::TypeReducer.new(CheeseType, {})
6
+ reducer = GraphQL::Schema::TypeReducer.new(CheeseType, type_map)
6
7
  expected = {
7
8
  "Cheese" => CheeseType,
8
9
  "Float" => GraphQL::FLOAT_TYPE,
@@ -13,13 +14,14 @@ describe GraphQL::Schema::TypeReducer do
13
14
  "Milk" => MilkType,
14
15
  "ID" => GraphQL::ID_TYPE,
15
16
  "AnimalProduct" => AnimalProductInterface,
17
+ "Honey" => HoneyType,
16
18
  }
17
19
  assert_equal(expected.keys, reducer.result.keys)
18
- assert_equal(expected, reducer.result)
20
+ assert_equal(expected, reducer.result.to_h)
19
21
  end
20
22
 
21
23
  it 'finds type from arguments' do
22
- reducer = GraphQL::Schema::TypeReducer.new(QueryType, {})
24
+ reducer = GraphQL::Schema::TypeReducer.new(QueryType, type_map)
23
25
  assert_equal(DairyProductInputType, reducer.result["DairyProductInput"])
24
26
  end
25
27
 
@@ -34,13 +36,13 @@ describe GraphQL::Schema::TypeReducer do
34
36
  input_field :child, type_child
35
37
  end
36
38
 
37
- reducer = GraphQL::Schema::TypeReducer.new(type_parent, {})
39
+ reducer = GraphQL::Schema::TypeReducer.new(type_parent, type_map)
38
40
  expected = {
39
41
  "InputTypeParent" => type_parent,
40
42
  "InputTypeChild" => type_child,
41
43
  "String" => GraphQL::STRING_TYPE
42
44
  }
43
- assert_equal(expected, reducer.result)
45
+ assert_equal(expected, reducer.result.to_h)
44
46
  end
45
47
 
46
48
  describe 'when a type is invalid' do
@@ -59,12 +61,12 @@ describe GraphQL::Schema::TypeReducer do
59
61
  }
60
62
 
61
63
  it 'raises an InvalidTypeError when passed nil' do
62
- reducer = GraphQL::Schema::TypeReducer.new(invalid_type, {})
64
+ reducer = GraphQL::Schema::TypeReducer.new(invalid_type, type_map)
63
65
  assert_raises(GraphQL::Schema::InvalidTypeError) { reducer.result }
64
66
  end
65
67
 
66
68
  it 'raises an InvalidTypeError when passed an object that isnt a GraphQL::BaseType' do
67
- reducer = GraphQL::Schema::TypeReducer.new(another_invalid_type, {})
69
+ reducer = GraphQL::Schema::TypeReducer.new(another_invalid_type, type_map)
68
70
  assert_raises(GraphQL::Schema::InvalidTypeError) { reducer.result }
69
71
  end
70
72
  end
@@ -93,4 +95,21 @@ describe GraphQL::Schema::TypeReducer do
93
95
  assert_raises(RuntimeError) { type_map["SomeType"] }
94
96
  end
95
97
  end
98
+
99
+ describe "when a type can only be inferred through an interface" do
100
+ it "logs a warning" do
101
+ out, err = capture_io do
102
+ GraphQL::Schema::TypeReducer.find_all([EdibleInterface])
103
+ end
104
+ assert_match /Type "Milk" was inferred from an interface/, err
105
+ assert_match /Type "Honey" was inferred from an interface/, err
106
+ end
107
+
108
+ it "is ok if the types are passed in explicitly" do
109
+ out, err = capture_io do
110
+ GraphQL::Schema::TypeReducer.find_all([EdibleInterface, HoneyType, MilkType])
111
+ end
112
+ assert_equal "", err
113
+ end
114
+ end
96
115
  end
@@ -73,6 +73,13 @@ MilkType = GraphQL::ObjectType.define do
73
73
  end
74
74
  end
75
75
 
76
+ # No actual data; This type is an "orphan", only accessible through Interfaces
77
+ HoneyType = GraphQL::ObjectType.define do
78
+ name 'Honey'
79
+ description "Sweet, dehydrated bee barf"
80
+ interfaces [EdibleInterface, AnimalProductInterface]
81
+ end
82
+
76
83
  DairyType = GraphQL::ObjectType.define do
77
84
  name 'Dairy'
78
85
  description 'A farm where milk is harvested and cheese is produced'
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: 0.12.0
4
+ version: 0.12.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-20 00:00:00.000000000 Z
11
+ date: 2016-04-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parslet
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: '2.4'
97
+ - !ruby/object:Gem::Dependency
98
+ name: listen
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 3.0.0
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 3.0.0
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: minitest
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -243,7 +257,6 @@ files:
243
257
  - lib/graphql/static_validation.rb
244
258
  - lib/graphql/static_validation/all_rules.rb
245
259
  - lib/graphql/static_validation/arguments_validator.rb
246
- - lib/graphql/static_validation/complexity_validator.rb
247
260
  - lib/graphql/static_validation/literal_validator.rb
248
261
  - lib/graphql/static_validation/message.rb
249
262
  - lib/graphql/static_validation/rules/argument_literals_are_compatible.rb
@@ -310,7 +323,6 @@ files:
310
323
  - spec/graphql/schema/type_reducer_spec.rb
311
324
  - spec/graphql/schema/type_validator_spec.rb
312
325
  - spec/graphql/schema_spec.rb
313
- - spec/graphql/static_validation/complexity_validator_spec.rb
314
326
  - spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb
315
327
  - spec/graphql/static_validation/rules/arguments_are_defined_spec.rb
316
328
  - spec/graphql/static_validation/rules/directives_are_defined_spec.rb
@@ -333,7 +345,6 @@ files:
333
345
  - spec/graphql/string_type_spec.rb
334
346
  - spec/graphql/union_type_spec.rb
335
347
  - spec/spec_helper.rb
336
- - spec/support/calculator_schema.rb
337
348
  - spec/support/dairy_app.rb
338
349
  - spec/support/dairy_data.rb
339
350
  - spec/support/minimum_input_object.rb
@@ -403,7 +414,6 @@ test_files:
403
414
  - spec/graphql/schema/type_reducer_spec.rb
404
415
  - spec/graphql/schema/type_validator_spec.rb
405
416
  - spec/graphql/schema_spec.rb
406
- - spec/graphql/static_validation/complexity_validator_spec.rb
407
417
  - spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb
408
418
  - spec/graphql/static_validation/rules/arguments_are_defined_spec.rb
409
419
  - spec/graphql/static_validation/rules/directives_are_defined_spec.rb
@@ -426,7 +436,6 @@ test_files:
426
436
  - spec/graphql/string_type_spec.rb
427
437
  - spec/graphql/union_type_spec.rb
428
438
  - spec/spec_helper.rb
429
- - spec/support/calculator_schema.rb
430
439
  - spec/support/dairy_app.rb
431
440
  - spec/support/dairy_data.rb
432
441
  - spec/support/minimum_input_object.rb
@@ -1,27 +0,0 @@
1
- class GraphQL::StaticValidation::ComplexityValidator
2
- include GraphQL::StaticValidation::Message::MessageHelper
3
-
4
- def initialize(max_fields:, list_multiplier:)
5
- @max_fields = max_fields
6
- @list_multiplier = list_multiplier
7
- end
8
-
9
- def validate(context)
10
- visitor = context.visitor
11
- complexity = 0
12
- visitor[GraphQL::Language::Nodes::Field] << -> (node, parent) {
13
- field_type = field_definition.type
14
- if field_type.kind.list?
15
- complexity += list_multiplier
16
- else
17
- complexity += 1
18
- end
19
- }
20
-
21
- visitor[GraphQL::Language::Nodes::Document].exit << -> (node, parent) {
22
- if complexity > @max_fields
23
- context.errors << message("This query is too complex. Request fewer fields.", node)
24
- end
25
- }
26
- end
27
- end
@@ -1,15 +0,0 @@
1
- # require "spec_helper"
2
- #
3
- # describe GraphQL::StaticValidation::ComplexityValidator do
4
- # let(:query_string) {query_string)}
5
- # let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [complexity_validator]) }
6
- # let(:errors) { validator.validate(document) }
7
- # let(:complexity_validator) { GraphQL::StaticValidation::ComplexityValidator.new(max_fields: 6, list_multiplier: 2) }
8
- #
9
- # describe "too many fields" do
10
- # it "adds errors if there are too many fields"
11
- # it "counts fields for each time they're included from fragments"
12
- # end
13
- #
14
- # it "multiplies fields inside list types"
15
- # end
@@ -1,74 +0,0 @@
1
- # This GraphQL Schema performs operations on numbers.
2
- # It can perform operations on values you give it and return values
3
- # It also maintains some state which can be updated or read
4
- module Calculator
5
- # You can reduce a list of values to a single value
6
- REDUCERS = {
7
- "SUM" => -> (values) { [values.inject(&:+)] },
8
- "MAX" => :max.to_proc,
9
- "MIN" => :min.to_proc,
10
- }
11
-
12
- ReducerEnum = GraphQL::EnumType.define do
13
- REDUCERS.map do |op_name, op_proc|
14
- value(op_name)
15
- end
16
- end
17
-
18
- # You can make a new list by transforming each member
19
- MAPPERS = {
20
- "ADD" => -> (val, arg) { val + arg },
21
- "SUB" => -> (val, arg) { val - arg },
22
- "EQ" => -> (val, arg) { val == arg ? 1 : 0},
23
- }
24
-
25
- MapperEnum = GraphQL::EnumType.define do
26
- MAPPERS.map do |op_name, op_proc|
27
- value(op_name)
28
- end
29
- end
30
-
31
- # Input a list of integers
32
- ListOfInts = GraphQL::INT_TYPE.to_list_type
33
-
34
- # Expose a list of values and perform operations
35
- ValuesType = GraphQL::ObjectType.define do
36
- field :values, ListOfInts do
37
- resolve -> (obj, _args, _ctx) { obj }
38
- end
39
-
40
- # Get a single value based on the values in this list
41
- field :reduce, types.Int do
42
- argument :operation, !ReducerEnum
43
- resolve -> (obj, args, ctx) {
44
- reduce_name = args[:operation]
45
- reduce_fn = REDUCERS[reduce_name]
46
- reduce_fn.call(obj)
47
- }
48
- end
49
-
50
- # Handle self-referential fields by wrapping the type in a proc.
51
- # It will be lazy-eval'ed
52
- field :map, -> { ValuesType } do
53
- argument :operation, !MapperEnum
54
- argument :argument, !types.Int
55
- resolve -> (obj, args, ctx) {
56
- op_arg = args[:argument]
57
- op_name = args[:operation]
58
- op_func = MAPPERS[op_name]
59
- obj.map { |item| op_func.call(item, op_arg) }
60
- }
61
- end
62
- end
63
-
64
- QueryType = GraphQL::ObjectType.define do
65
- name("Query")
66
-
67
- field :perform, ValuesType do
68
- argument :initial, !ListOfInts
69
- resolve -> (obj, args, ctx) { args[:initial] }
70
- end
71
- end
72
-
73
- Schema = GraphQL::Schema.new(query: QueryType)
74
- end