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.
- checksums.yaml +4 -4
- data/lib/graphql.rb +2 -0
- data/lib/graphql/base_type.rb +79 -0
- data/lib/graphql/enum_type.rb +1 -3
- data/lib/graphql/input_object_type.rb +2 -2
- data/lib/graphql/interface_type.rb +3 -22
- data/lib/graphql/list_type.rb +5 -3
- data/lib/graphql/non_null_type.rb +4 -2
- data/lib/graphql/object_type.rb +1 -34
- data/lib/graphql/query.rb +10 -5
- data/lib/graphql/query/arguments.rb +1 -1
- data/lib/graphql/query/base_execution.rb +21 -2
- data/lib/graphql/query/base_execution/value_resolution.rb +82 -0
- data/lib/graphql/query/executor.rb +7 -5
- data/lib/graphql/query/parallel_execution.rb +101 -0
- data/lib/graphql/query/serial_execution/field_resolution.rb +18 -9
- data/lib/graphql/scalar_type.rb +3 -3
- data/lib/graphql/schema.rb +4 -0
- data/lib/graphql/schema/type_map.rb +34 -0
- data/lib/graphql/schema/type_reducer.rb +14 -16
- data/lib/graphql/static_validation/arguments_validator.rb +8 -8
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +6 -8
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +7 -11
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +1 -1
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +1 -1
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +25 -4
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +2 -2
- data/lib/graphql/static_validation/type_stack.rb +3 -3
- data/lib/graphql/type_kinds.rb +0 -19
- data/lib/graphql/union_type.rb +3 -13
- data/lib/graphql/version.rb +1 -1
- data/readme.md +0 -11
- data/spec/graphql/base_type_spec.rb +24 -0
- data/spec/graphql/object_type_spec.rb +0 -20
- data/spec/graphql/query/parallel_execution_spec.rb +29 -0
- data/spec/graphql/query_spec.rb +23 -6
- data/spec/graphql/schema/type_reducer_spec.rb +25 -0
- data/spec/graphql/static_validation/validator_spec.rb +4 -3
- data/spec/spec_helper.rb +1 -1
- data/spec/support/dairy_app.rb +6 -2
- data/spec/support/parallel_schema.rb +31 -0
- metadata +26 -3
- 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
|
data/spec/graphql/query_spec.rb
CHANGED
@@ -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
|
-
|
162
|
-
|
163
|
-
|
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:
|
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
|
-
|
45
|
+
# nonsenseField, nonsenseArg, bogusField, bogusArg
|
46
|
+
assert_equal(4, errors.length)
|
46
47
|
end
|
47
48
|
end
|
48
49
|
|
data/spec/spec_helper.rb
CHANGED
data/spec/support/dairy_app.rb
CHANGED
@@ -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) {
|
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.
|
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-
|
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
|