graphql 1.1.0 → 1.2.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/analysis/analyze_query.rb +4 -2
- data/lib/graphql/analysis/field_usage.rb +4 -4
- data/lib/graphql/analysis/query_complexity.rb +16 -21
- data/lib/graphql/argument.rb +13 -6
- data/lib/graphql/base_type.rb +2 -1
- data/lib/graphql/compatibility/execution_specification.rb +76 -0
- data/lib/graphql/compatibility/query_parser_specification.rb +16 -2
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -5
- data/lib/graphql/compatibility/schema_parser_specification.rb +6 -0
- data/lib/graphql/define/assign_argument.rb +8 -2
- data/lib/graphql/define/instance_definable.rb +12 -15
- data/lib/graphql/directive.rb +2 -1
- data/lib/graphql/enum_type.rb +5 -7
- data/lib/graphql/field.rb +6 -11
- data/lib/graphql/field/resolve.rb +1 -0
- data/lib/graphql/input_object_type.rb +9 -9
- data/lib/graphql/interface_type.rb +2 -1
- data/lib/graphql/internal_representation.rb +1 -0
- data/lib/graphql/internal_representation/node.rb +31 -9
- data/lib/graphql/internal_representation/rewrite.rb +26 -26
- data/lib/graphql/internal_representation/selections.rb +41 -0
- data/lib/graphql/introspection/input_value_type.rb +6 -2
- data/lib/graphql/language/generation.rb +2 -0
- data/lib/graphql/language/lexer.rl +4 -0
- data/lib/graphql/language/nodes.rb +3 -0
- data/lib/graphql/language/parser.rb +525 -509
- data/lib/graphql/language/parser.y +2 -0
- data/lib/graphql/object_type.rb +2 -2
- data/lib/graphql/query.rb +21 -0
- data/lib/graphql/query/context.rb +52 -4
- data/lib/graphql/query/serial_execution.rb +3 -4
- data/lib/graphql/query/serial_execution/field_resolution.rb +35 -36
- data/lib/graphql/query/serial_execution/operation_resolution.rb +9 -15
- data/lib/graphql/query/serial_execution/selection_resolution.rb +14 -11
- data/lib/graphql/query/serial_execution/value_resolution.rb +18 -17
- data/lib/graphql/query/variables.rb +1 -1
- data/lib/graphql/relay/mutation.rb +5 -8
- data/lib/graphql/scalar_type.rb +1 -2
- data/lib/graphql/schema.rb +2 -13
- data/lib/graphql/schema/build_from_definition.rb +28 -13
- data/lib/graphql/schema/loader.rb +4 -1
- data/lib/graphql/schema/printer.rb +10 -3
- data/lib/graphql/schema/timeout_middleware.rb +18 -2
- data/lib/graphql/schema/unique_within_type.rb +6 -3
- data/lib/graphql/static_validation/literal_validator.rb +3 -1
- data/lib/graphql/union_type.rb +1 -2
- data/lib/graphql/version.rb +1 -1
- data/readme.md +1 -0
- data/spec/graphql/analysis/analyze_query_spec.rb +6 -8
- data/spec/graphql/argument_spec.rb +18 -0
- data/spec/graphql/define/assign_argument_spec.rb +48 -0
- data/spec/graphql/define/instance_definable_spec.rb +4 -2
- data/spec/graphql/execution_error_spec.rb +66 -0
- data/spec/graphql/input_object_type_spec.rb +81 -0
- data/spec/graphql/internal_representation/rewrite_spec.rb +104 -21
- data/spec/graphql/introspection/input_value_type_spec.rb +43 -6
- data/spec/graphql/introspection/schema_type_spec.rb +1 -0
- data/spec/graphql/introspection/type_type_spec.rb +2 -0
- data/spec/graphql/language/generation_spec.rb +3 -2
- data/spec/graphql/query/arguments_spec.rb +17 -4
- data/spec/graphql/query/context_spec.rb +23 -0
- data/spec/graphql/query/variables_spec.rb +15 -1
- data/spec/graphql/relay/mutation_spec.rb +42 -2
- data/spec/graphql/schema/build_from_definition_spec.rb +4 -2
- data/spec/graphql/schema/loader_spec.rb +59 -1
- data/spec/graphql/schema/printer_spec.rb +2 -0
- data/spec/graphql/schema/reduce_types_spec.rb +1 -1
- data/spec/graphql/schema/timeout_middleware_spec.rb +2 -2
- data/spec/graphql/schema/unique_within_type_spec.rb +9 -0
- data/spec/graphql/schema/validation_spec.rb +15 -3
- data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +122 -0
- data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +78 -0
- data/spec/support/dairy_app.rb +9 -0
- data/spec/support/minimum_input_object.rb +4 -0
- data/spec/support/star_wars_schema.rb +1 -1
- metadata +5 -5
- data/lib/graphql/query/serial_execution/execution_context.rb +0 -37
- data/spec/graphql/query/serial_execution/execution_context_spec.rb +0 -54
data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb
CHANGED
@@ -43,4 +43,82 @@ describe GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTyped do
|
|
43
43
|
]
|
44
44
|
assert_equal(expected, errors)
|
45
45
|
end
|
46
|
+
|
47
|
+
describe "null default values" do
|
48
|
+
describe "variables with valid default null values" do
|
49
|
+
let(:schema) {
|
50
|
+
GraphQL::Schema.from_definition(%|
|
51
|
+
type Query {
|
52
|
+
field(a: Int, b: String, c: ComplexInput): Int
|
53
|
+
}
|
54
|
+
|
55
|
+
input ComplexInput {
|
56
|
+
requiredField: Boolean!
|
57
|
+
intField: Int
|
58
|
+
}
|
59
|
+
|)
|
60
|
+
}
|
61
|
+
|
62
|
+
let(:query_string) {%|
|
63
|
+
query getCheese(
|
64
|
+
$a: Int = null,
|
65
|
+
$b: String = null,
|
66
|
+
$c: ComplexInput = { requiredField: true, intField: null }
|
67
|
+
) {
|
68
|
+
field(a: $a, b: $b, c: $c)
|
69
|
+
}
|
70
|
+
|}
|
71
|
+
|
72
|
+
it "finds no errors" do
|
73
|
+
assert_equal [], errors
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "variables with invalid default null values" do
|
78
|
+
let(:schema) {
|
79
|
+
GraphQL::Schema.from_definition(%|
|
80
|
+
type Query {
|
81
|
+
field(a: Int!, b: String!, c: ComplexInput): Int
|
82
|
+
}
|
83
|
+
|
84
|
+
input ComplexInput {
|
85
|
+
requiredField: Boolean!
|
86
|
+
intField: Int
|
87
|
+
}
|
88
|
+
|)
|
89
|
+
}
|
90
|
+
|
91
|
+
let(:query_string) {%|
|
92
|
+
query getCheese(
|
93
|
+
$a: Int! = null,
|
94
|
+
$b: String! = null,
|
95
|
+
$c: ComplexInput = { requiredField: null, intField: null }
|
96
|
+
) {
|
97
|
+
field(a: $a, b: $b, c: $c)
|
98
|
+
}
|
99
|
+
|}
|
100
|
+
|
101
|
+
it "finds errors" do
|
102
|
+
expected = [
|
103
|
+
{
|
104
|
+
"message"=>"Non-null variable $a can't have a default value",
|
105
|
+
"locations"=>[{"line"=>3, "column"=>11}],
|
106
|
+
"fields"=>["query getCheese"]
|
107
|
+
},
|
108
|
+
{
|
109
|
+
"message"=>"Non-null variable $b can't have a default value",
|
110
|
+
"locations"=>[{"line"=>4, "column"=>11}],
|
111
|
+
"fields"=>["query getCheese"]
|
112
|
+
},
|
113
|
+
{
|
114
|
+
"message"=>"Default value for $c doesn't match type ComplexInput",
|
115
|
+
"locations"=>[{"line"=>5, "column"=>11}],
|
116
|
+
"fields"=>["query getCheese"]
|
117
|
+
}
|
118
|
+
]
|
119
|
+
|
120
|
+
assert_equal expected, errors
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
46
124
|
end
|
data/spec/support/dairy_app.rb
CHANGED
@@ -16,6 +16,7 @@ EdibleInterface = GraphQL::InterfaceType.define do
|
|
16
16
|
description "Something you can eat, yum"
|
17
17
|
field :fatContent, !types.Float, "Percentage which is fat"
|
18
18
|
field :origin, !types.String, "Place the edible comes from"
|
19
|
+
field :selfAsEdible, EdibleInterface, resolve: ->(o, a, c) { o }
|
19
20
|
end
|
20
21
|
|
21
22
|
AnimalProductInterface = GraphQL::InterfaceType.define do
|
@@ -297,6 +298,14 @@ DairyAppQueryType = GraphQL::ObjectType.define do
|
|
297
298
|
resolve ->(t, a, c) { raise(GraphQL::ExecutionError, "There was an execution error") }
|
298
299
|
end
|
299
300
|
|
301
|
+
field :valueWithExecutionError do
|
302
|
+
type !GraphQL::INT_TYPE
|
303
|
+
resolve ->(t, a, c) {
|
304
|
+
c.add_error(GraphQL::ExecutionError.new("Could not fetch latest value"))
|
305
|
+
return 0
|
306
|
+
}
|
307
|
+
end
|
308
|
+
|
300
309
|
# To test possibly-null fields
|
301
310
|
field :maybeNull, MaybeNullType do
|
302
311
|
resolve ->(t, a, c) { OpenStruct.new(cheese: nil) }
|
@@ -147,7 +147,7 @@ IntroduceShipMutation = GraphQL::Relay::Mutation.define do
|
|
147
147
|
description "Add a ship to this faction"
|
148
148
|
|
149
149
|
# Nested under `input` in the query:
|
150
|
-
input_field :shipName,
|
150
|
+
input_field :shipName, types.String
|
151
151
|
input_field :factionId, !types.ID
|
152
152
|
|
153
153
|
# Result may have access to these fields:
|
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.
|
4
|
+
version: 1.2.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: 2016-11-
|
11
|
+
date: 2016-11-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: codeclimate-test-reporter
|
@@ -306,6 +306,7 @@ files:
|
|
306
306
|
- lib/graphql/internal_representation.rb
|
307
307
|
- lib/graphql/internal_representation/node.rb
|
308
308
|
- lib/graphql/internal_representation/rewrite.rb
|
309
|
+
- lib/graphql/internal_representation/selections.rb
|
309
310
|
- lib/graphql/introspection.rb
|
310
311
|
- lib/graphql/introspection/arguments_field.rb
|
311
312
|
- lib/graphql/introspection/directive_location_enum.rb
|
@@ -348,7 +349,6 @@ files:
|
|
348
349
|
- lib/graphql/query/input_validation_result.rb
|
349
350
|
- lib/graphql/query/literal_input.rb
|
350
351
|
- lib/graphql/query/serial_execution.rb
|
351
|
-
- lib/graphql/query/serial_execution/execution_context.rb
|
352
352
|
- lib/graphql/query/serial_execution/field_resolution.rb
|
353
353
|
- lib/graphql/query/serial_execution/operation_resolution.rb
|
354
354
|
- lib/graphql/query/serial_execution/selection_resolution.rb
|
@@ -432,6 +432,7 @@ files:
|
|
432
432
|
- spec/graphql/compatibility/execution_specification_spec.rb
|
433
433
|
- spec/graphql/compatibility/query_parser_specification_spec.rb
|
434
434
|
- spec/graphql/compatibility/schema_parser_specification_spec.rb
|
435
|
+
- spec/graphql/define/assign_argument_spec.rb
|
435
436
|
- spec/graphql/define/instance_definable_spec.rb
|
436
437
|
- spec/graphql/directive_spec.rb
|
437
438
|
- spec/graphql/enum_type_spec.rb
|
@@ -462,7 +463,6 @@ files:
|
|
462
463
|
- spec/graphql/query/arguments_spec.rb
|
463
464
|
- spec/graphql/query/context_spec.rb
|
464
465
|
- spec/graphql/query/executor_spec.rb
|
465
|
-
- spec/graphql/query/serial_execution/execution_context_spec.rb
|
466
466
|
- spec/graphql/query/serial_execution/value_resolution_spec.rb
|
467
467
|
- spec/graphql/query/variables_spec.rb
|
468
468
|
- spec/graphql/query_spec.rb
|
@@ -556,6 +556,7 @@ test_files:
|
|
556
556
|
- spec/graphql/compatibility/execution_specification_spec.rb
|
557
557
|
- spec/graphql/compatibility/query_parser_specification_spec.rb
|
558
558
|
- spec/graphql/compatibility/schema_parser_specification_spec.rb
|
559
|
+
- spec/graphql/define/assign_argument_spec.rb
|
559
560
|
- spec/graphql/define/instance_definable_spec.rb
|
560
561
|
- spec/graphql/directive_spec.rb
|
561
562
|
- spec/graphql/enum_type_spec.rb
|
@@ -586,7 +587,6 @@ test_files:
|
|
586
587
|
- spec/graphql/query/arguments_spec.rb
|
587
588
|
- spec/graphql/query/context_spec.rb
|
588
589
|
- spec/graphql/query/executor_spec.rb
|
589
|
-
- spec/graphql/query/serial_execution/execution_context_spec.rb
|
590
590
|
- spec/graphql/query/serial_execution/value_resolution_spec.rb
|
591
591
|
- spec/graphql/query/variables_spec.rb
|
592
592
|
- spec/graphql/query_spec.rb
|
@@ -1,37 +0,0 @@
|
|
1
|
-
module GraphQL
|
2
|
-
class Query
|
3
|
-
class SerialExecution
|
4
|
-
class ExecutionContext
|
5
|
-
attr_reader :query, :schema, :strategy
|
6
|
-
|
7
|
-
def initialize(query, strategy)
|
8
|
-
@query = query
|
9
|
-
@schema = query.schema
|
10
|
-
@strategy = strategy
|
11
|
-
@warden = query.warden
|
12
|
-
end
|
13
|
-
|
14
|
-
def get_type(type_name)
|
15
|
-
@warden.get_type(type_name)
|
16
|
-
end
|
17
|
-
|
18
|
-
def get_fragment(name)
|
19
|
-
@query.fragments[name]
|
20
|
-
end
|
21
|
-
|
22
|
-
def get_field(type, irep_node)
|
23
|
-
# fall back for dynamic fields (eg __typename)
|
24
|
-
irep_node.definitions[type] || @warden.get_field(type, irep_node.definition_name) || raise("No field found on #{type.name} for '#{irep_node.definition_name}' (#{irep_node.ast_node.name})")
|
25
|
-
end
|
26
|
-
|
27
|
-
def possible_types(type)
|
28
|
-
@warden.possible_types(type)
|
29
|
-
end
|
30
|
-
|
31
|
-
def add_error(err)
|
32
|
-
@query.context.errors << err
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,54 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe GraphQL::Query::SerialExecution::ExecutionContext do
|
4
|
-
let(:query_string) { %|
|
5
|
-
query getFlavor($cheeseId: Int!) {
|
6
|
-
brie: cheese(id: 1) { ...cheeseFields, taste: flavor }
|
7
|
-
}
|
8
|
-
fragment cheeseFields on Cheese { flavor }
|
9
|
-
|}
|
10
|
-
let(:operation_name) { nil }
|
11
|
-
let(:query_variables) { {"cheeseId" => 2} }
|
12
|
-
let(:schema) { DummySchema }
|
13
|
-
let(:query) { GraphQL::Query.new(
|
14
|
-
schema,
|
15
|
-
query_string,
|
16
|
-
variables: query_variables,
|
17
|
-
operation_name: operation_name,
|
18
|
-
)}
|
19
|
-
let(:execution_context) {
|
20
|
-
GraphQL::Query::SerialExecution::ExecutionContext.new(query, nil)
|
21
|
-
}
|
22
|
-
|
23
|
-
describe "add_error" do
|
24
|
-
let(:err) { StandardError.new("test") }
|
25
|
-
let(:expected) { [err] }
|
26
|
-
|
27
|
-
it "adds an error on the query context" do
|
28
|
-
execution_context.add_error(err)
|
29
|
-
assert_equal(expected, query.context.errors)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
describe "get_type" do
|
34
|
-
it "returns the respective type from the schema" do
|
35
|
-
type = execution_context.get_type("Dairy")
|
36
|
-
assert_equal(DairyType, type)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe "get_field" do
|
41
|
-
it "returns the respective field from the schema" do
|
42
|
-
irep_node = OpenStruct.new(definition_name: "cheese", definitions: {DairyType => DairyType.fields["cheese"]})
|
43
|
-
field = execution_context.get_field(DairyType, irep_node)
|
44
|
-
assert_equal("cheese", field.name)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
describe "get_fragment" do
|
49
|
-
it "returns a fragment on the query by name" do
|
50
|
-
fragment = execution_context.get_fragment("cheeseFields")
|
51
|
-
assert_equal("cheeseFields", fragment.name)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|