graphql 0.7.1 → 0.8.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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql.rb +2 -0
  3. data/lib/graphql/base_type.rb +79 -0
  4. data/lib/graphql/enum_type.rb +1 -3
  5. data/lib/graphql/input_object_type.rb +2 -2
  6. data/lib/graphql/interface_type.rb +3 -22
  7. data/lib/graphql/list_type.rb +5 -3
  8. data/lib/graphql/non_null_type.rb +4 -2
  9. data/lib/graphql/object_type.rb +1 -34
  10. data/lib/graphql/query.rb +10 -5
  11. data/lib/graphql/query/arguments.rb +1 -1
  12. data/lib/graphql/query/base_execution.rb +21 -2
  13. data/lib/graphql/query/base_execution/value_resolution.rb +82 -0
  14. data/lib/graphql/query/executor.rb +7 -5
  15. data/lib/graphql/query/parallel_execution.rb +101 -0
  16. data/lib/graphql/query/serial_execution/field_resolution.rb +18 -9
  17. data/lib/graphql/scalar_type.rb +3 -3
  18. data/lib/graphql/schema.rb +4 -0
  19. data/lib/graphql/schema/type_map.rb +34 -0
  20. data/lib/graphql/schema/type_reducer.rb +14 -16
  21. data/lib/graphql/static_validation/arguments_validator.rb +8 -8
  22. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +6 -8
  23. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +7 -11
  24. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +1 -1
  25. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +1 -1
  26. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +1 -1
  27. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +25 -4
  28. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +2 -2
  29. data/lib/graphql/static_validation/type_stack.rb +3 -3
  30. data/lib/graphql/type_kinds.rb +0 -19
  31. data/lib/graphql/union_type.rb +3 -13
  32. data/lib/graphql/version.rb +1 -1
  33. data/readme.md +0 -11
  34. data/spec/graphql/base_type_spec.rb +24 -0
  35. data/spec/graphql/object_type_spec.rb +0 -20
  36. data/spec/graphql/query/parallel_execution_spec.rb +29 -0
  37. data/spec/graphql/query_spec.rb +23 -6
  38. data/spec/graphql/schema/type_reducer_spec.rb +25 -0
  39. data/spec/graphql/static_validation/validator_spec.rb +4 -3
  40. data/spec/spec_helper.rb +1 -1
  41. data/spec/support/dairy_app.rb +6 -2
  42. data/spec/support/parallel_schema.rb +31 -0
  43. metadata +26 -3
  44. data/lib/graphql/query/value_resolution.rb +0 -76
@@ -18,26 +18,6 @@ describe GraphQL::ObjectType do
18
18
  assert_equal([EdibleInterface, AnimalProductInterface], type.interfaces)
19
19
  end
20
20
 
21
- it 'becomes non-null with !' do
22
- non_null_type = !type
23
- assert_equal(GraphQL::TypeKinds::NON_NULL, non_null_type.kind)
24
- assert_equal(type, non_null_type.of_type)
25
- assert_equal(GraphQL::TypeKinds::NON_NULL, (!GraphQL::STRING_TYPE).kind)
26
- end
27
-
28
- it 'can be compared' do
29
- assert_equal(!GraphQL::INT_TYPE, !GraphQL::INT_TYPE)
30
- refute_equal(!GraphQL::FLOAT_TYPE, GraphQL::FLOAT_TYPE)
31
- assert_equal(
32
- GraphQL::ListType.new(of_type: MilkType),
33
- GraphQL::ListType.new(of_type: MilkType)
34
- )
35
- refute_equal(
36
- GraphQL::ListType.new(of_type: MilkType),
37
- GraphQL::ListType.new(of_type: !MilkType)
38
- )
39
- end
40
-
41
21
  describe '.fields ' do
42
22
  it 'exposes fields' do
43
23
  field = type.fields["id"]
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe GraphQL::Query::ParallelExecution do
4
+ let(:result) { GraphQL::Query.new(SlowSchema, query_string).result }
5
+ describe "fields that take a long time" do
6
+ let(:query_string) {%|
7
+ {
8
+ slow1: slow { slow1, slow2, slows { slow1 } }
9
+ slow2: slow { slow1, slow2, lastSlow: slow3 }
10
+ }
11
+ |}
12
+
13
+ it "runs them in parallel, not in sequence" do
14
+ elapsed = Benchmark.realtime { result }
15
+ assert elapsed < 0.7, "It takes less that the sum of all sleeps"
16
+
17
+ expected = { "data" => {
18
+ "slow1" => { "slow1" => 1, "slow2" => 1, "slows" => [
19
+ { "slow1" => 1 },
20
+ { "slow1" => 1 },
21
+ { "slow1" => 1 },
22
+ ]
23
+ },
24
+ "slow2" => { "slow1" => 1, "slow2" => 1, "lastSlow" => 1},
25
+ }}
26
+ assert_equal expected, result, "It renders the right result"
27
+ end
28
+ end
29
+ end
@@ -151,16 +151,33 @@ describe GraphQL::Query do
151
151
  argument :key, !types.String
152
152
  resolve -> (target, args, ctx) { ctx[args[:key]] }
153
153
  end
154
+ field :contextAstNodeName, types.String do
155
+ resolve -> (target, args, ctx) { ctx.ast_node.class.name }
156
+ end
154
157
  }}
155
158
  let(:schema) { GraphQL::Schema.new(query: query_type, mutation: nil)}
156
159
  let(:query) { GraphQL::Query.new(schema, query_string, context: {"some_key" => "some value"})}
157
- let(:query_string) { %|
158
- query getCtx { context(key: "some_key") }
159
- |}
160
160
 
161
- it 'passes context to fields' do
162
- expected = {"data" => {"context" => "some value"}}
163
- assert_equal(expected, query.result)
161
+ describe "access to passed-in values" do
162
+ let(:query_string) { %|
163
+ query getCtx { context(key: "some_key") }
164
+ |}
165
+
166
+ it 'passes context to fields' do
167
+ expected = {"data" => {"context" => "some value"}}
168
+ assert_equal(expected, query.result)
169
+ end
170
+ end
171
+
172
+ describe "access to the AST node" do
173
+ let(:query_string) { %|
174
+ query getCtx { contextAstNodeName }
175
+ |}
176
+
177
+ it 'provides access to the AST node' do
178
+ expected = {"data" => {"contextAstNodeName" => "GraphQL::Language::Nodes::Field"}}
179
+ assert_equal(expected, query.result)
180
+ end
164
181
  end
165
182
  end
166
183
  end
@@ -36,4 +36,29 @@ describe GraphQL::Schema::TypeReducer do
36
36
  assert_raises(GraphQL::Schema::InvalidTypeError) { reducer.result }
37
37
  end
38
38
  end
39
+
40
+ describe 'when a schema has multiple types with the same name' do
41
+ let(:type_1) {
42
+ GraphQL::ObjectType.define do
43
+ name "MyType"
44
+ end
45
+ }
46
+ let(:type_2) {
47
+ GraphQL::ObjectType.define do
48
+ name "MyType"
49
+ end
50
+ }
51
+ it 'raises an error' do
52
+ assert_raises(RuntimeError) {
53
+ GraphQL::Schema::TypeReducer.find_all([type_1, type_2])
54
+ }
55
+ end
56
+ end
57
+
58
+ describe 'when getting a type which doesnt exist' do
59
+ it 'raises an error' do
60
+ type_map = GraphQL::Schema::TypeReducer.find_all([])
61
+ assert_raises(RuntimeError) { type_map["SomeType"] }
62
+ end
63
+ end
39
64
  end
@@ -31,8 +31,8 @@ describe GraphQL::StaticValidation::Validator do
31
31
 
32
32
  describe 'fields & arguments' do
33
33
  let(:query_string) { %|
34
- query getCheese {
35
- cheese(id: 1) {
34
+ query getCheese($id: Int!) {
35
+ cheese(id: $id, bogusArg: true) {
36
36
  source,
37
37
  nonsenseField,
38
38
  id(nonsenseArg: 1)
@@ -42,7 +42,8 @@ describe GraphQL::StaticValidation::Validator do
42
42
  |}
43
43
 
44
44
  it 'handles args on invalid fields' do
45
- assert_equal(3, errors.length)
45
+ # nonsenseField, nonsenseArg, bogusField, bogusArg
46
+ assert_equal(4, errors.length)
46
47
  end
47
48
  end
48
49
 
@@ -1,7 +1,7 @@
1
1
  require "codeclimate-test-reporter"
2
2
  CodeClimate::TestReporter.start
3
3
  require 'graphql'
4
- require 'date'
4
+ require "benchmark"
5
5
  require "minitest/autorun"
6
6
  require "minitest/focus"
7
7
  require "minitest/reporters"
@@ -40,7 +40,11 @@ CheeseType = GraphQL::ObjectType.define do
40
40
  type -> { CheeseType }
41
41
  description("Cheeses like this one")
42
42
  argument :source, !types[!DairyAnimalEnum]
43
- resolve -> (t, a, c) { CHEESES.values.find { |c| c.source == a["source"] } }
43
+ resolve -> (t, a, c) {
44
+ c.async do
45
+ CHEESES.values.find { |c| c.source == a["source"] }
46
+ end
47
+ }
44
48
  end
45
49
 
46
50
  field :fatContent, property: :fat_content do
@@ -157,7 +161,7 @@ QueryType = GraphQL::ObjectType.define do
157
161
  field :error do
158
162
  description "Raise an error"
159
163
  type GraphQL::STRING_TYPE
160
- resolve -> (t, a, c) { raise("This error was raised on purpose") }
164
+ resolve -> (t, a, c) { c.async { raise("This error was raised on purpose") } }
161
165
  end
162
166
 
163
167
  # To test possibly-null fields
@@ -0,0 +1,31 @@
1
+
2
+ def create_slow_field
3
+ GraphQL::Field.define do
4
+ type(types.Int)
5
+ resolve -> (obj, args, ctx) {
6
+ ctx.async {
7
+ sleep 0.3
8
+ 1
9
+ }
10
+ }
11
+ end
12
+ end
13
+
14
+ SlowType = GraphQL::ObjectType.define do
15
+ name "Slow"
16
+ field :slow1, field: create_slow_field
17
+ field :slow2, field: create_slow_field
18
+ field :slow3, field: create_slow_field
19
+ field :slows, -> { types[SlowType] } do
20
+ resolve -> (o, a, ctx) { ctx.async { [:slow, :slow, :slow] } }
21
+ end
22
+ end
23
+
24
+ SlowQueryType = GraphQL::ObjectType.define do
25
+ name "Query"
26
+ field :slow, SlowType do
27
+ resolve -> (o, a, c) { :slow }
28
+ end
29
+ end
30
+
31
+ SlowSchema = GraphQL::Schema.new(query: SlowQueryType)
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.7.1
4
+ version: 0.8.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: 2015-08-27 00:00:00.000000000 Z
11
+ date: 2015-09-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parslet
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: celluloid
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.17'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.17'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: codeclimate-test-reporter
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -161,6 +175,7 @@ files:
161
175
  - MIT-LICENSE
162
176
  - lib/graphql.rb
163
177
  - lib/graphql/argument.rb
178
+ - lib/graphql/base_type.rb
164
179
  - lib/graphql/boolean_type.rb
165
180
  - lib/graphql/definition_helpers.rb
166
181
  - lib/graphql/definition_helpers/defined_by_config.rb
@@ -208,8 +223,10 @@ files:
208
223
  - lib/graphql/query/arguments.rb
209
224
  - lib/graphql/query/base_execution.rb
210
225
  - lib/graphql/query/base_execution/selected_object_resolution.rb
226
+ - lib/graphql/query/base_execution/value_resolution.rb
211
227
  - lib/graphql/query/directive_chain.rb
212
228
  - lib/graphql/query/executor.rb
229
+ - lib/graphql/query/parallel_execution.rb
213
230
  - lib/graphql/query/serial_execution.rb
214
231
  - lib/graphql/query/serial_execution/field_resolution.rb
215
232
  - lib/graphql/query/serial_execution/fragment_spread_resolution.rb
@@ -217,13 +234,13 @@ files:
217
234
  - lib/graphql/query/serial_execution/operation_resolution.rb
218
235
  - lib/graphql/query/serial_execution/selection_resolution.rb
219
236
  - lib/graphql/query/type_resolver.rb
220
- - lib/graphql/query/value_resolution.rb
221
237
  - lib/graphql/repl.rb
222
238
  - lib/graphql/scalar_type.rb
223
239
  - lib/graphql/schema.rb
224
240
  - lib/graphql/schema/each_item_validator.rb
225
241
  - lib/graphql/schema/field_validator.rb
226
242
  - lib/graphql/schema/implementation_validator.rb
243
+ - lib/graphql/schema/type_map.rb
227
244
  - lib/graphql/schema/type_reducer.rb
228
245
  - lib/graphql/schema/type_validator.rb
229
246
  - lib/graphql/static_validation.rb
@@ -254,6 +271,7 @@ files:
254
271
  - lib/graphql/union_type.rb
255
272
  - lib/graphql/version.rb
256
273
  - readme.md
274
+ - spec/graphql/base_type_spec.rb
257
275
  - spec/graphql/directive_spec.rb
258
276
  - spec/graphql/enum_type_spec.rb
259
277
  - spec/graphql/field_spec.rb
@@ -269,6 +287,7 @@ files:
269
287
  - spec/graphql/language/visitor_spec.rb
270
288
  - spec/graphql/object_type_spec.rb
271
289
  - spec/graphql/query/executor_spec.rb
290
+ - spec/graphql/query/parallel_execution_spec.rb
272
291
  - spec/graphql/query_spec.rb
273
292
  - spec/graphql/schema/field_validator_spec.rb
274
293
  - spec/graphql/schema/type_reducer_spec.rb
@@ -295,6 +314,7 @@ files:
295
314
  - spec/spec_helper.rb
296
315
  - spec/support/dairy_app.rb
297
316
  - spec/support/dairy_data.rb
317
+ - spec/support/parallel_schema.rb
298
318
  - spec/support/star_wars_data.rb
299
319
  - spec/support/star_wars_schema.rb
300
320
  homepage: http://github.com/rmosolgo/graphql-ruby
@@ -322,6 +342,7 @@ signing_key:
322
342
  specification_version: 4
323
343
  summary: A GraphQL implementation for Ruby
324
344
  test_files:
345
+ - spec/graphql/base_type_spec.rb
325
346
  - spec/graphql/directive_spec.rb
326
347
  - spec/graphql/enum_type_spec.rb
327
348
  - spec/graphql/field_spec.rb
@@ -337,6 +358,7 @@ test_files:
337
358
  - spec/graphql/language/visitor_spec.rb
338
359
  - spec/graphql/object_type_spec.rb
339
360
  - spec/graphql/query/executor_spec.rb
361
+ - spec/graphql/query/parallel_execution_spec.rb
340
362
  - spec/graphql/query_spec.rb
341
363
  - spec/graphql/schema/field_validator_spec.rb
342
364
  - spec/graphql/schema/type_reducer_spec.rb
@@ -363,5 +385,6 @@ test_files:
363
385
  - spec/spec_helper.rb
364
386
  - spec/support/dairy_app.rb
365
387
  - spec/support/dairy_data.rb
388
+ - spec/support/parallel_schema.rb
366
389
  - spec/support/star_wars_data.rb
367
390
  - spec/support/star_wars_schema.rb
@@ -1,76 +0,0 @@
1
- module GraphQL
2
- class Query
3
- module ValueResolution
4
- def self.get_strategy_for_kind(kind)
5
- TYPE_KIND_STRATEGIES[kind] || raise("No value resolution strategy for #{kind}!")
6
- end
7
-
8
- class BaseResolution
9
- attr_reader :value, :field_type, :target, :parent_type,
10
- :ast_field, :query, :execution_strategy
11
- def initialize(value, field_type, target, parent_type, ast_field, query, execution_strategy)
12
- @value = value
13
- @field_type = field_type
14
- @target = target
15
- @parent_type = parent_type
16
- @ast_field = ast_field
17
- @query = query
18
- @execution_strategy = execution_strategy
19
- end
20
-
21
- def result
22
- raise NotImplementedError, "Should return a value based on initialization params"
23
- end
24
- end
25
-
26
- class ScalarResolution < BaseResolution
27
- def result
28
- field_type.coerce(value)
29
- end
30
- end
31
-
32
- class ListResolution < BaseResolution
33
- def result
34
- wrapped_type = field_type.of_type
35
- value.map do |item|
36
- resolved_type = wrapped_type.kind.resolve(wrapped_type, item)
37
- strategy_class = GraphQL::Query::ValueResolution.get_strategy_for_kind(resolved_type.kind)
38
- inner_strategy = strategy_class.new(item, resolved_type, target, parent_type, ast_field, query, execution_strategy)
39
- inner_strategy.result
40
- end
41
- end
42
- end
43
-
44
- class ObjectResolution < BaseResolution
45
- def result
46
- resolver = execution_strategy.selection_resolution.new(value, field_type, ast_field.selections, query, execution_strategy)
47
- resolver.result
48
- end
49
- end
50
-
51
- class EnumResolution < BaseResolution
52
- def result
53
- value.to_s
54
- end
55
- end
56
-
57
- class NonNullResolution < BaseResolution
58
- def result
59
- wrapped_type = field_type.of_type
60
- resolved_type = wrapped_type.kind.resolve(wrapped_type, value)
61
- strategy_class = GraphQL::Query::ValueResolution.get_strategy_for_kind(resolved_type.kind)
62
- inner_strategy = strategy_class.new(value, resolved_type, target, parent_type, ast_field, query, execution_strategy)
63
- inner_strategy.result
64
- end
65
- end
66
-
67
- TYPE_KIND_STRATEGIES = {
68
- GraphQL::TypeKinds::SCALAR => ScalarResolution,
69
- GraphQL::TypeKinds::LIST => ListResolution,
70
- GraphQL::TypeKinds::OBJECT => ObjectResolution,
71
- GraphQL::TypeKinds::ENUM => EnumResolution,
72
- GraphQL::TypeKinds::NON_NULL => NonNullResolution,
73
- }
74
- end
75
- end
76
- end