graphql 1.8.3 → 1.8.4
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 +4 -1
- data/lib/graphql/argument.rb +1 -0
- data/lib/graphql/authorization.rb +81 -0
- data/lib/graphql/boolean_type.rb +0 -1
- data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +2 -1
- data/lib/graphql/execution/execute.rb +34 -10
- data/lib/graphql/execution/lazy.rb +5 -1
- data/lib/graphql/field.rb +7 -1
- data/lib/graphql/float_type.rb +0 -1
- data/lib/graphql/id_type.rb +0 -1
- data/lib/graphql/int_type.rb +0 -1
- data/lib/graphql/introspection/entry_points.rb +2 -2
- data/lib/graphql/object_type.rb +3 -3
- data/lib/graphql/query.rb +6 -0
- data/lib/graphql/query/arguments.rb +2 -0
- data/lib/graphql/query/context.rb +6 -0
- data/lib/graphql/query/variables.rb +7 -1
- data/lib/graphql/relay/connection_instrumentation.rb +2 -2
- data/lib/graphql/relay/connection_resolve.rb +7 -27
- data/lib/graphql/relay/connection_type.rb +1 -0
- data/lib/graphql/relay/edge_type.rb +1 -0
- data/lib/graphql/relay/edges_instrumentation.rb +9 -25
- data/lib/graphql/relay/mutation/instrumentation.rb +1 -2
- data/lib/graphql/relay/mutation/resolve.rb +2 -4
- data/lib/graphql/relay/node.rb +1 -6
- data/lib/graphql/relay/page_info.rb +1 -9
- data/lib/graphql/schema.rb +84 -11
- data/lib/graphql/schema/argument.rb +13 -0
- data/lib/graphql/schema/enum.rb +1 -1
- data/lib/graphql/schema/enum_value.rb +4 -0
- data/lib/graphql/schema/field.rb +44 -11
- data/lib/graphql/schema/interface.rb +20 -0
- data/lib/graphql/schema/introspection_system.rb +1 -1
- data/lib/graphql/schema/member/base_dsl_methods.rb +25 -3
- data/lib/graphql/schema/member/instrumentation.rb +15 -17
- data/lib/graphql/schema/mutation.rb +4 -0
- data/lib/graphql/schema/object.rb +33 -0
- data/lib/graphql/schema/possible_types.rb +2 -0
- data/lib/graphql/schema/resolver.rb +10 -0
- data/lib/graphql/schema/traversal.rb +9 -2
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +11 -2
- data/lib/graphql/string_type.rb +0 -1
- data/lib/graphql/types.rb +7 -0
- data/lib/graphql/types/relay.rb +31 -0
- data/lib/graphql/types/relay/base_connection.rb +87 -0
- data/lib/graphql/types/relay/base_edge.rb +51 -0
- data/lib/graphql/types/relay/base_field.rb +22 -0
- data/lib/graphql/types/relay/base_interface.rb +29 -0
- data/lib/graphql/types/relay/base_object.rb +26 -0
- data/lib/graphql/types/relay/node.rb +18 -0
- data/lib/graphql/types/relay/page_info.rb +23 -0
- data/lib/graphql/unauthorized_error.rb +20 -0
- data/lib/graphql/version.rb +1 -1
- data/spec/graphql/authorization_spec.rb +684 -0
- data/spec/graphql/query/variables_spec.rb +20 -0
- data/spec/graphql/relay/connection_instrumentation_spec.rb +1 -1
- data/spec/graphql/schema/resolver_spec.rb +31 -0
- data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +52 -0
- data/spec/support/dummy/schema.rb +16 -0
- data/spec/support/star_wars/schema.rb +28 -17
- metadata +15 -2
@@ -110,6 +110,26 @@ describe GraphQL::Query::Variables do
|
|
110
110
|
assert_equal expected, variables.errors.first.message
|
111
111
|
end
|
112
112
|
end
|
113
|
+
|
114
|
+
describe "when provided input cannot be coerced" do
|
115
|
+
let(:query_string) {%|
|
116
|
+
query searchMyDairy (
|
117
|
+
$time: Time
|
118
|
+
) {
|
119
|
+
searchDairy(expiresAfter: $time) {
|
120
|
+
... on Cheese {
|
121
|
+
flavor
|
122
|
+
}
|
123
|
+
}
|
124
|
+
}
|
125
|
+
|}
|
126
|
+
let(:provided_variables) { { "time" => "a" } }
|
127
|
+
|
128
|
+
it "validates invalid input objects" do
|
129
|
+
expected = "Variable time of type Time was provided invalid value"
|
130
|
+
assert_equal expected, variables.errors.first.message
|
131
|
+
end
|
132
|
+
end
|
113
133
|
end
|
114
134
|
|
115
135
|
describe "nullable variables" do
|
@@ -77,7 +77,7 @@ describe GraphQL::Relay::ConnectionInstrumentation do
|
|
77
77
|
# Before the object is wrapped in a connection, the instrumentation sees `Array`
|
78
78
|
assert_equal ["StarWars::FactionRecord", "Array", "GraphQL::Relay::ArrayConnection"], ctx[:before_built_ins]
|
79
79
|
# After the object is wrapped in a connection, it sees the connection object
|
80
|
-
assert_equal ["StarWars::Faction", "GraphQL::Relay::ArrayConnection", "GraphQL::Relay::
|
80
|
+
assert_equal ["StarWars::Faction", "GraphQL::Relay::ArrayConnection", "GraphQL::Types::Relay::PageInfo"], ctx[:after_built_ins]
|
81
81
|
end
|
82
82
|
end
|
83
83
|
end
|
@@ -49,6 +49,21 @@ describe GraphQL::Schema::Resolver do
|
|
49
49
|
class Resolver5 < Resolver4
|
50
50
|
end
|
51
51
|
|
52
|
+
class Resolver6 < Resolver1
|
53
|
+
type Integer, null: false
|
54
|
+
|
55
|
+
def resolve
|
56
|
+
self.class.complexity
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class Resolver7 < Resolver6
|
61
|
+
complexity 2
|
62
|
+
end
|
63
|
+
|
64
|
+
class Resolver8 < Resolver7
|
65
|
+
end
|
66
|
+
|
52
67
|
class Query < GraphQL::Schema::Object
|
53
68
|
class CustomField < GraphQL::Schema::Field
|
54
69
|
def resolve_field(*args)
|
@@ -68,6 +83,9 @@ describe GraphQL::Schema::Resolver do
|
|
68
83
|
field :resolver_3_again, resolver: Resolver3, description: "field desc"
|
69
84
|
field :resolver_4, "Positional description", resolver: Resolver4
|
70
85
|
field :resolver_5, resolver: Resolver5
|
86
|
+
field :resolver_6, resolver: Resolver6
|
87
|
+
field :resolver_7, resolver: Resolver7
|
88
|
+
field :resolver_8, resolver: Resolver8
|
71
89
|
end
|
72
90
|
|
73
91
|
class Schema < GraphQL::Schema
|
@@ -114,6 +132,19 @@ describe GraphQL::Schema::Resolver do
|
|
114
132
|
end
|
115
133
|
end
|
116
134
|
|
135
|
+
describe "complexity" do
|
136
|
+
it "has default values" do
|
137
|
+
res = ResolverTest::Schema.execute " { resolver6 } ", root_value: OpenStruct.new(value: 0)
|
138
|
+
assert_equal 1, res["data"]["resolver6"]
|
139
|
+
end
|
140
|
+
|
141
|
+
it "is inherited" do
|
142
|
+
res = ResolverTest::Schema.execute " { resolver7 resolver8 } ", root_value: OpenStruct.new(value: 0)
|
143
|
+
assert_equal 2, res["data"]["resolver7"]
|
144
|
+
assert_equal 2, res["data"]["resolver8"]
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
117
148
|
describe "when applied to a field" do
|
118
149
|
it "gets the field's description" do
|
119
150
|
assert_nil ResolverTest::Schema.find("Query.resolver3").description
|
data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb
CHANGED
@@ -134,4 +134,56 @@ describe GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTyped do
|
|
134
134
|
end
|
135
135
|
end
|
136
136
|
end
|
137
|
+
|
138
|
+
describe "custom error messages" do
|
139
|
+
let(:schema) {
|
140
|
+
TimeType = GraphQL::ScalarType.define do
|
141
|
+
name "Time"
|
142
|
+
description "Time since epoch in seconds"
|
143
|
+
|
144
|
+
coerce_input ->(value, ctx) do
|
145
|
+
begin
|
146
|
+
Time.at(Float(value))
|
147
|
+
rescue ArgumentError
|
148
|
+
raise GraphQL::CoercionError, 'cannot coerce to Float'
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
coerce_result ->(value, ctx) { value.to_f }
|
153
|
+
end
|
154
|
+
|
155
|
+
QueryType = GraphQL::ObjectType.define do
|
156
|
+
name "Query"
|
157
|
+
description "The query root of this schema"
|
158
|
+
|
159
|
+
field :time do
|
160
|
+
type TimeType
|
161
|
+
argument :value, !TimeType
|
162
|
+
resolve ->(obj, args, ctx) { args[:value] }
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
GraphQL::Schema.define do
|
167
|
+
query QueryType
|
168
|
+
end
|
169
|
+
}
|
170
|
+
|
171
|
+
let(:query_string) {%|
|
172
|
+
query(
|
173
|
+
$value: Time = "a"
|
174
|
+
) {
|
175
|
+
time(value: $value)
|
176
|
+
}
|
177
|
+
|}
|
178
|
+
|
179
|
+
it "sets error message from a CoercionError if raised" do
|
180
|
+
assert_equal 1, errors.length
|
181
|
+
|
182
|
+
assert_includes errors, {
|
183
|
+
"message"=> "cannot coerce to Float",
|
184
|
+
"locations"=>[{"line"=>3, "column"=>9}],
|
185
|
+
"fields"=>["query"]
|
186
|
+
}
|
187
|
+
end
|
188
|
+
end
|
137
189
|
end
|
@@ -248,6 +248,21 @@ module Dummy
|
|
248
248
|
end
|
249
249
|
end
|
250
250
|
|
251
|
+
TimeType = GraphQL::ScalarType.define do
|
252
|
+
name "Time"
|
253
|
+
description "Time since epoch in seconds"
|
254
|
+
|
255
|
+
coerce_input ->(value, ctx) do
|
256
|
+
begin
|
257
|
+
Time.at(Float(value))
|
258
|
+
rescue ArgumentError
|
259
|
+
raise GraphQL::CoercionError, 'cannot coerce to Float'
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
coerce_result ->(value, ctx) { value.to_f }
|
264
|
+
end
|
265
|
+
|
251
266
|
class FetchItem < GraphQL::Function
|
252
267
|
attr_reader :type, :description, :arguments
|
253
268
|
|
@@ -312,6 +327,7 @@ module Dummy
|
|
312
327
|
type !DairyProductUnion
|
313
328
|
# This is a list just for testing 😬
|
314
329
|
argument :product, types[DairyProductInputType], default_value: [{"source" => "SHEEP"}]
|
330
|
+
argument :expiresAfter, TimeType
|
315
331
|
resolve ->(t, args, c) {
|
316
332
|
source = args["product"][0][:source] # String or Sym is ok
|
317
333
|
products = CHEESES.values + MILKS.values
|
@@ -27,12 +27,23 @@ module StarWars
|
|
27
27
|
field :planet, String, null: true
|
28
28
|
end
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
30
|
+
|
31
|
+
class BaseEdge < GraphQL::Types::Relay::BaseEdge
|
32
|
+
node_type(BaseType)
|
33
|
+
end
|
34
|
+
|
35
|
+
class BaseConnection < GraphQL::Types::Relay::BaseConnection
|
36
|
+
edge_type(BaseEdge)
|
37
|
+
end
|
38
|
+
|
39
|
+
class BasesConnectionWithTotalCountType < GraphQL::Types::Relay::BaseConnection
|
40
|
+
edge_type(BaseEdge)
|
41
|
+
nodes_field
|
42
|
+
|
43
|
+
field :total_count, Integer, null: true
|
44
|
+
|
45
|
+
def total_count
|
46
|
+
object.nodes.count
|
36
47
|
end
|
37
48
|
end
|
38
49
|
|
@@ -121,7 +132,7 @@ module StarWars
|
|
121
132
|
|
122
133
|
field :shipsWithMaxPageSize, "Ships with max page size", max_page_size: 2, function: ShipsWithMaxPageSize.new
|
123
134
|
|
124
|
-
field :bases,
|
135
|
+
field :bases, BasesConnectionWithTotalCountType, null: true, connection: true, resolve: ->(obj, args, ctx) {
|
125
136
|
all_bases = Base.where(id: obj.bases)
|
126
137
|
if args[:nameIncludes]
|
127
138
|
all_bases = all_bases.where("name LIKE ?", "%#{args[:nameIncludes]}%")
|
@@ -131,8 +142,8 @@ module StarWars
|
|
131
142
|
argument :nameIncludes, String, required: false
|
132
143
|
end
|
133
144
|
|
134
|
-
field :basesClone,
|
135
|
-
field :basesByName,
|
145
|
+
field :basesClone, BaseConnection, null: true
|
146
|
+
field :basesByName, BaseConnection, null: true do
|
136
147
|
argument :order, String, default_value: "name", required: false
|
137
148
|
end
|
138
149
|
def bases_by_name(order: nil)
|
@@ -143,13 +154,13 @@ module StarWars
|
|
143
154
|
end
|
144
155
|
end
|
145
156
|
|
146
|
-
field :basesWithMaxLimitRelation,
|
147
|
-
field :basesWithMaxLimitArray,
|
148
|
-
field :basesWithDefaultMaxLimitRelation,
|
149
|
-
field :basesWithDefaultMaxLimitArray,
|
150
|
-
field :basesWithLargeMaxLimitRelation,
|
157
|
+
field :basesWithMaxLimitRelation, BaseConnection, null: true, max_page_size: 2, resolve: Proc.new { Base.all}
|
158
|
+
field :basesWithMaxLimitArray, BaseConnection, null: true, max_page_size: 2, resolve: Proc.new { Base.all.to_a }
|
159
|
+
field :basesWithDefaultMaxLimitRelation, BaseConnection, null: true, resolve: Proc.new { Base.all }
|
160
|
+
field :basesWithDefaultMaxLimitArray, BaseConnection, null: true, resolve: Proc.new { Base.all.to_a }
|
161
|
+
field :basesWithLargeMaxLimitRelation, BaseConnection, null: true, max_page_size: 1000, resolve: Proc.new { Base.all }
|
151
162
|
|
152
|
-
field :basesAsSequelDataset,
|
163
|
+
field :basesAsSequelDataset, BasesConnectionWithTotalCountType, null: true, connection: true, max_page_size: 1000 do
|
153
164
|
argument :nameIncludes, String, required: false
|
154
165
|
end
|
155
166
|
|
@@ -297,14 +308,14 @@ module StarWars
|
|
297
308
|
|
298
309
|
field :largestBase, BaseType, null: true, resolve: ->(obj, args, ctx) { Base.find(3) }
|
299
310
|
|
300
|
-
field :newestBasesGroupedByFaction,
|
311
|
+
field :newestBasesGroupedByFaction, BaseConnection, null: true, resolve: ->(obj, args, ctx) {
|
301
312
|
Base
|
302
313
|
.having('id in (select max(id) from bases group by faction_id)')
|
303
314
|
.group(:id)
|
304
315
|
.order('faction_id desc')
|
305
316
|
}
|
306
317
|
|
307
|
-
field :basesWithNullName,
|
318
|
+
field :basesWithNullName, BaseConnection, null: false, resolve: ->(obj, args, ctx) {
|
308
319
|
[OpenStruct.new(id: nil)]
|
309
320
|
}
|
310
321
|
|
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.8.
|
4
|
+
version: 1.8.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Mosolgo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-06-
|
11
|
+
date: 2018-06-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: benchmark-ips
|
@@ -348,6 +348,7 @@ files:
|
|
348
348
|
- lib/graphql/analysis/reducer_state.rb
|
349
349
|
- lib/graphql/analysis_error.rb
|
350
350
|
- lib/graphql/argument.rb
|
351
|
+
- lib/graphql/authorization.rb
|
351
352
|
- lib/graphql/backtrace.rb
|
352
353
|
- lib/graphql/backtrace/inspect_result.rb
|
353
354
|
- lib/graphql/backtrace/table.rb
|
@@ -588,12 +589,22 @@ files:
|
|
588
589
|
- lib/graphql/tracing/scout_tracing.rb
|
589
590
|
- lib/graphql/tracing/skylight_tracing.rb
|
590
591
|
- lib/graphql/type_kinds.rb
|
592
|
+
- lib/graphql/types.rb
|
591
593
|
- lib/graphql/types/boolean.rb
|
592
594
|
- lib/graphql/types/float.rb
|
593
595
|
- lib/graphql/types/id.rb
|
594
596
|
- lib/graphql/types/int.rb
|
595
597
|
- lib/graphql/types/iso_8601_date_time.rb
|
598
|
+
- lib/graphql/types/relay.rb
|
599
|
+
- lib/graphql/types/relay/base_connection.rb
|
600
|
+
- lib/graphql/types/relay/base_edge.rb
|
601
|
+
- lib/graphql/types/relay/base_field.rb
|
602
|
+
- lib/graphql/types/relay/base_interface.rb
|
603
|
+
- lib/graphql/types/relay/base_object.rb
|
604
|
+
- lib/graphql/types/relay/node.rb
|
605
|
+
- lib/graphql/types/relay/page_info.rb
|
596
606
|
- lib/graphql/types/string.rb
|
607
|
+
- lib/graphql/unauthorized_error.rb
|
597
608
|
- lib/graphql/union_type.rb
|
598
609
|
- lib/graphql/unresolved_type_error.rb
|
599
610
|
- lib/graphql/upgrader/member.rb
|
@@ -966,6 +977,7 @@ files:
|
|
966
977
|
- spec/graphql/analysis/query_complexity_spec.rb
|
967
978
|
- spec/graphql/analysis/query_depth_spec.rb
|
968
979
|
- spec/graphql/argument_spec.rb
|
980
|
+
- spec/graphql/authorization_spec.rb
|
969
981
|
- spec/graphql/backtrace_spec.rb
|
970
982
|
- spec/graphql/base_type_spec.rb
|
971
983
|
- spec/graphql/boolean_type_spec.rb
|
@@ -1514,6 +1526,7 @@ test_files:
|
|
1514
1526
|
- spec/graphql/analysis/query_complexity_spec.rb
|
1515
1527
|
- spec/graphql/analysis/query_depth_spec.rb
|
1516
1528
|
- spec/graphql/argument_spec.rb
|
1529
|
+
- spec/graphql/authorization_spec.rb
|
1517
1530
|
- spec/graphql/backtrace_spec.rb
|
1518
1531
|
- spec/graphql/base_type_spec.rb
|
1519
1532
|
- spec/graphql/boolean_type_spec.rb
|