graphql 1.9.0.pre4 → 1.9.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 +1 -0
- data/lib/graphql/execution/execute.rb +16 -14
- data/lib/graphql/execution/interpreter/runtime.rb +14 -12
- data/lib/graphql/integer_encoding_error.rb +12 -0
- data/lib/graphql/schema.rb +11 -8
- data/lib/graphql/schema/default_type_error.rb +1 -1
- data/lib/graphql/schema/member/instrumentation.rb +10 -7
- data/lib/graphql/schema/resolver.rb +10 -10
- data/lib/graphql/tracing.rb +6 -1
- data/lib/graphql/types/float.rb +1 -1
- data/lib/graphql/types/int.rb +11 -2
- data/lib/graphql/version.rb +1 -1
- data/readme.md +7 -7
- data/spec/dummy/config/locales/en.yml +1 -1
- data/spec/graphql/int_type_spec.rb +19 -0
- data/spec/graphql/language/document_from_schema_definition_spec.rb +2 -2
- data/spec/support/dummy/schema.rb +12 -0
- data/spec/support/jazz.rb +7 -5
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fb79bf185d3d89d53f50ad5f0ae1cc93e3480acb
|
4
|
+
data.tar.gz: 46c04d4e296ea2b3b520d6df50f82d76da5ec641
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 78e070c3df4abd9e2d649ba0e5f1e7fdcef9b0241572a30bf233d516fa28b7eee9afa0fd2d650db835556dff87f4eddb344aefce8825019569aa7e55ff28f780
|
7
|
+
data.tar.gz: eb138cb5d2274c815ea42ec2eff4371cf34023ad817e4009302cb6de6da7deea213ccfaa2169d86a6a8c2b684f9e4fc8bd0780060163a764960d22af1a48bb25
|
data/lib/graphql.rb
CHANGED
@@ -89,6 +89,7 @@ require "graphql/runtime_type_error"
|
|
89
89
|
require "graphql/invalid_null_error"
|
90
90
|
require "graphql/invalid_name_error"
|
91
91
|
require "graphql/unresolved_type_error"
|
92
|
+
require "graphql/integer_encoding_error"
|
92
93
|
require "graphql/string_encoding_error"
|
93
94
|
require "graphql/query"
|
94
95
|
require "graphql/internal_representation"
|
@@ -281,20 +281,22 @@ module GraphQL
|
|
281
281
|
)
|
282
282
|
when GraphQL::TypeKinds::UNION, GraphQL::TypeKinds::INTERFACE
|
283
283
|
query = field_ctx.query
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
284
|
+
resolved_type_or_lazy = field_type.resolve_type(value, field_ctx)
|
285
|
+
query.schema.after_lazy(resolved_type_or_lazy) do |resolved_type|
|
286
|
+
possible_types = query.possible_types(field_type)
|
287
|
+
|
288
|
+
if !possible_types.include?(resolved_type)
|
289
|
+
parent_type = field_ctx.irep_node.owner_type
|
290
|
+
type_error = GraphQL::UnresolvedTypeError.new(value, field_defn, parent_type, resolved_type, possible_types)
|
291
|
+
field_ctx.schema.type_error(type_error, field_ctx)
|
292
|
+
PROPAGATE_NULL
|
293
|
+
else
|
294
|
+
resolve_value(
|
295
|
+
value,
|
296
|
+
resolved_type,
|
297
|
+
field_ctx,
|
298
|
+
)
|
299
|
+
end
|
298
300
|
end
|
299
301
|
else
|
300
302
|
raise("Unknown type kind: #{field_type.kind}")
|
@@ -270,18 +270,20 @@ module GraphQL
|
|
270
270
|
write_in_response(path, r)
|
271
271
|
r
|
272
272
|
when "UNION", "INTERFACE"
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
273
|
+
resolved_type_or_lazy = query.resolve_type(type, value)
|
274
|
+
after_lazy(resolved_type_or_lazy, path: path, field: field) do |resolved_type|
|
275
|
+
possible_types = query.possible_types(type)
|
276
|
+
|
277
|
+
if !possible_types.include?(resolved_type)
|
278
|
+
parent_type = field.owner
|
279
|
+
type_error = GraphQL::UnresolvedTypeError.new(value, field, parent_type, resolved_type, possible_types)
|
280
|
+
schema.type_error(type_error, context)
|
281
|
+
write_in_response(path, nil)
|
282
|
+
nil
|
283
|
+
else
|
284
|
+
resolved_type = resolved_type.metadata[:type_class]
|
285
|
+
continue_field(path, value, field, resolved_type, ast_node, next_selections, is_non_null)
|
286
|
+
end
|
285
287
|
end
|
286
288
|
when "OBJECT"
|
287
289
|
object_proxy = begin
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
class IntegerEncodingError < GraphQL::RuntimeTypeError
|
4
|
+
# The value which couldn't be encoded
|
5
|
+
attr_reader :integer_value
|
6
|
+
|
7
|
+
def initialize(value)
|
8
|
+
@integer_value = value
|
9
|
+
super('Integer out of bounds.')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/lib/graphql/schema.rb
CHANGED
@@ -509,17 +509,20 @@ module GraphQL
|
|
509
509
|
yield(type, object, ctx)
|
510
510
|
end
|
511
511
|
|
512
|
-
if type_result.respond_to?(:graphql_definition)
|
513
|
-
type_result = type_result.graphql_definition
|
514
|
-
end
|
515
|
-
|
516
512
|
if type_result.nil?
|
517
513
|
nil
|
518
|
-
elsif !type_result.is_a?(GraphQL::BaseType)
|
519
|
-
type_str = "#{type_result} (#{type_result.class.name})"
|
520
|
-
raise "resolve_type(#{object}) returned #{type_str}, but it should return a GraphQL type"
|
521
514
|
else
|
522
|
-
type_result
|
515
|
+
after_lazy(type_result) do |resolved_type_result|
|
516
|
+
if resolved_type_result.respond_to?(:graphql_definition)
|
517
|
+
resolved_type_result = resolved_type_result.graphql_definition
|
518
|
+
end
|
519
|
+
if !resolved_type_result.is_a?(GraphQL::BaseType)
|
520
|
+
type_str = "#{resolved_type_result} (#{resolved_type_result.class.name})"
|
521
|
+
raise "resolve_type(#{object}) returned #{type_str}, but it should return a GraphQL type"
|
522
|
+
else
|
523
|
+
resolved_type_result
|
524
|
+
end
|
525
|
+
end
|
523
526
|
end
|
524
527
|
end
|
525
528
|
|
@@ -6,7 +6,7 @@ module GraphQL
|
|
6
6
|
case type_error
|
7
7
|
when GraphQL::InvalidNullError
|
8
8
|
ctx.errors << type_error
|
9
|
-
when GraphQL::UnresolvedTypeError, GraphQL::StringEncodingError
|
9
|
+
when GraphQL::UnresolvedTypeError, GraphQL::StringEncodingError, GraphQL::IntegerEncodingError
|
10
10
|
raise type_error
|
11
11
|
end
|
12
12
|
end
|
@@ -91,7 +91,7 @@ module GraphQL
|
|
91
91
|
# For lists with nil, we need another nil check here
|
92
92
|
nil
|
93
93
|
else
|
94
|
-
|
94
|
+
concrete_type_or_lazy = case @inner_return_type
|
95
95
|
when GraphQL::UnionType, GraphQL::InterfaceType
|
96
96
|
ctx.query.resolve_type(@inner_return_type, inner_obj)
|
97
97
|
when GraphQL::ObjectType
|
@@ -100,12 +100,15 @@ module GraphQL
|
|
100
100
|
raise "unexpected proxying type #{@inner_return_type} for #{inner_obj} at #{ctx.owner_type}.#{ctx.field.name}"
|
101
101
|
end
|
102
102
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
103
|
+
# .resolve_type may have returned a lazy
|
104
|
+
ctx.schema.after_lazy(concrete_type_or_lazy) do |concrete_type|
|
105
|
+
if concrete_type && (object_class = concrete_type.metadata[:type_class])
|
106
|
+
# use the query-level context here, since it won't be field-specific anyways
|
107
|
+
query_ctx = ctx.query.context
|
108
|
+
object_class.authorized_new(inner_obj, query_ctx)
|
109
|
+
else
|
110
|
+
inner_obj
|
111
|
+
end
|
109
112
|
end
|
110
113
|
end
|
111
114
|
end
|
@@ -200,13 +200,13 @@ module GraphQL
|
|
200
200
|
# See if any object can be found for this ID
|
201
201
|
loaded_application_object = object_from_id(lookup_as_type, id, context)
|
202
202
|
context.schema.after_lazy(loaded_application_object) do |application_object|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
203
|
+
if application_object.nil?
|
204
|
+
raise LoadApplicationObjectFailedError.new(argument: argument, id: id, object: application_object)
|
205
|
+
end
|
206
|
+
# Double-check that the located object is actually of this type
|
207
|
+
# (Don't want to allow arbitrary access to objects this way)
|
208
|
+
resolved_application_object_type = context.schema.resolve_type(lookup_as_type, application_object, context)
|
209
|
+
context.schema.after_lazy(resolved_application_object_type) do |application_object_type|
|
210
210
|
possible_object_types = context.schema.possible_types(lookup_as_type)
|
211
211
|
if !possible_object_types.include?(application_object_type)
|
212
212
|
raise LoadApplicationObjectFailedError.new(argument: argument, id: id, object: application_object)
|
@@ -230,11 +230,11 @@ module GraphQL
|
|
230
230
|
application_object
|
231
231
|
end
|
232
232
|
end
|
233
|
-
rescue LoadApplicationObjectFailedError => err
|
234
|
-
# pass it to a handler
|
235
|
-
load_application_object_failed(err)
|
236
233
|
end
|
237
234
|
end
|
235
|
+
rescue LoadApplicationObjectFailedError => err
|
236
|
+
# pass it to a handler
|
237
|
+
load_application_object_failed(err)
|
238
238
|
end
|
239
239
|
|
240
240
|
def load_application_object_failed(err)
|
data/lib/graphql/tracing.rb
CHANGED
@@ -27,7 +27,7 @@ module GraphQL
|
|
27
27
|
# tracer MyTracer # <= responds to .trace(key, data, &block)
|
28
28
|
# end
|
29
29
|
#
|
30
|
-
# @example Adding a tracer to a query
|
30
|
+
# @example Adding a tracer to a single query
|
31
31
|
# MySchema.execute(query_str, context: { backtrace: true })
|
32
32
|
#
|
33
33
|
# Events:
|
@@ -45,6 +45,11 @@ module GraphQL
|
|
45
45
|
# execute_field | `{ context: GraphQL::Query::Context::FieldResolutionContext?, field: GraphQL::Schema::Field?, path: Array<String, Integer>?}`
|
46
46
|
# execute_field_lazy | `{ context: GraphQL::Query::Context::FieldResolutionContext?, field: GraphQL::Schema::Field?, path: Array<String, Integer>?}`
|
47
47
|
#
|
48
|
+
# Note that `execute_field` and `execute_field_lazy` receive different data in different settings:
|
49
|
+
#
|
50
|
+
# - When using {GraphQL::Execution::Interpreter}, they receive `{field:, path:}`
|
51
|
+
# - Otherwise, they receive `{context: ...}`
|
52
|
+
#
|
48
53
|
module Tracing
|
49
54
|
# Objects may include traceable to gain a `.trace(...)` method.
|
50
55
|
# The object must have a `@tracers` ivar of type `Array<<#trace(k, d, &b)>>`.
|
data/lib/graphql/types/float.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module GraphQL
|
4
4
|
module Types
|
5
5
|
class Float < GraphQL::Schema::Scalar
|
6
|
-
description "Represents signed double-precision fractional values as specified by [IEEE 754](
|
6
|
+
description "Represents signed double-precision fractional values as specified by [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point)."
|
7
7
|
|
8
8
|
def self.coerce_input(value, _ctx)
|
9
9
|
value.is_a?(Numeric) ? value.to_f : nil
|
data/lib/graphql/types/int.rb
CHANGED
@@ -5,12 +5,21 @@ module GraphQL
|
|
5
5
|
class Int < GraphQL::Schema::Scalar
|
6
6
|
description "Represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1."
|
7
7
|
|
8
|
+
MIN = -(2**31)
|
9
|
+
MAX = (2**31) - 1
|
10
|
+
|
8
11
|
def self.coerce_input(value, _ctx)
|
9
12
|
value.is_a?(Numeric) ? value.to_i : nil
|
10
13
|
end
|
11
14
|
|
12
|
-
def self.coerce_result(value,
|
13
|
-
value.to_i
|
15
|
+
def self.coerce_result(value, ctx)
|
16
|
+
value = value.to_i
|
17
|
+
if value >= MIN && value <= MAX
|
18
|
+
value
|
19
|
+
else
|
20
|
+
err = GraphQL::IntegerEncodingError.new(value)
|
21
|
+
ctx.schema.type_error(err, ctx)
|
22
|
+
end
|
14
23
|
end
|
15
24
|
|
16
25
|
default_scalar true
|
data/lib/graphql/version.rb
CHANGED
data/readme.md
CHANGED
@@ -4,12 +4,12 @@
|
|
4
4
|
[](https://rubygems.org/gems/graphql)
|
5
5
|
[](https://codeclimate.com/github/rmosolgo/graphql-ruby)
|
6
6
|
[](https://codeclimate.com/github/rmosolgo/graphql-ruby)
|
7
|
-
[](
|
7
|
+
[](https://rmosolgo.github.io/react-badges/)
|
8
8
|
|
9
|
-
A Ruby implementation of [GraphQL](
|
9
|
+
A Ruby implementation of [GraphQL](https://graphql.org/).
|
10
10
|
|
11
|
-
- [Website](https://
|
12
|
-
- [API Documentation](
|
11
|
+
- [Website](https://graphql-ruby.org/)
|
12
|
+
- [API Documentation](https://www.rubydoc.info/gems/graphql)
|
13
13
|
- [Newsletter](https://tinyletter.com/graphql-ruby)
|
14
14
|
|
15
15
|
## Installation
|
@@ -33,11 +33,11 @@ $ rails generate graphql:install
|
|
33
33
|
|
34
34
|
After this, you may need to run `bundle install` again, as by default graphiql-rails is added on installation.
|
35
35
|
|
36
|
-
Or, see ["Getting Started"](https://
|
36
|
+
Or, see ["Getting Started"](https://graphql-ruby.org/).
|
37
37
|
|
38
38
|
## Upgrade
|
39
39
|
|
40
|
-
I also sell [GraphQL::Pro](
|
40
|
+
I also sell [GraphQL::Pro](https://graphql.pro) which provides several features on top of the GraphQL runtime, including [Pundit authorization](https://graphql-ruby.org/authorization/pundit_integration), [CanCan authorization](https://graphql-ruby.org/authorization/can_can_integration), [Pusher-based subscriptions](https://graphql-ruby.org/subscriptions/pusher_implementation) and [persisted queries](https://graphql-ruby.org/operation_store/overview). Besides that, Pro customers get email support and an opportunity to support graphql-ruby's development!
|
41
41
|
|
42
42
|
## Goals
|
43
43
|
|
@@ -49,4 +49,4 @@ I also sell [GraphQL::Pro](http://graphql.pro) which provides several features o
|
|
49
49
|
|
50
50
|
- __Say hi & ask questions__ in the [#ruby channel on Slack](https://graphql-slack.herokuapp.com/) or [on Twitter](https://twitter.com/rmosolgo)!
|
51
51
|
- __Report bugs__ by posting a description, full stack trace, and all relevant code in a [GitHub issue](https://github.com/rmosolgo/graphql-ruby/issues).
|
52
|
-
- __Start hacking__ with the [Development guide](
|
52
|
+
- __Start hacking__ with the [Development guide](https://graphql-ruby.org/development).
|
@@ -12,5 +12,24 @@ describe GraphQL::INT_TYPE do
|
|
12
12
|
assert_nil GraphQL::INT_TYPE.coerce_isolated_input("55")
|
13
13
|
assert_nil GraphQL::INT_TYPE.coerce_isolated_input(true)
|
14
14
|
end
|
15
|
+
|
16
|
+
describe "handling boundaries" do
|
17
|
+
let(:context) { GraphQL::Query.new(Dummy::Schema, "{ __typename }").context }
|
18
|
+
|
19
|
+
it "accepts result values in bounds" do
|
20
|
+
assert_equal 0, GraphQL::INT_TYPE.coerce_result(0, context)
|
21
|
+
assert_equal (2**31) - 1, GraphQL::INT_TYPE.coerce_result((2**31) - 1, context)
|
22
|
+
assert_equal -(2**31), GraphQL::INT_TYPE.coerce_result(-(2**31), context)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "replaces values, if configured to do so" do
|
26
|
+
assert_equal Dummy::Schema::MAGIC_INT_COERCE_VALUE, GraphQL::INT_TYPE.coerce_result(99**99, context)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "raises on values out of bounds" do
|
30
|
+
assert_raises(GraphQL::IntegerEncodingError) { GraphQL::INT_TYPE.coerce_result(2**31, context) }
|
31
|
+
assert_raises(GraphQL::IntegerEncodingError) { GraphQL::INT_TYPE.coerce_result(-(2**31 + 1), context) }
|
32
|
+
end
|
33
|
+
end
|
15
34
|
end
|
16
35
|
end
|
@@ -433,7 +433,7 @@ describe GraphQL::Language::DocumentFromSchemaDefinition do
|
|
433
433
|
}
|
434
434
|
|
435
435
|
# Represents signed double-precision fractional values as specified by [IEEE
|
436
|
-
# 754](
|
436
|
+
# 754](https://en.wikipedia.org/wiki/IEEE_floating_point).
|
437
437
|
scalar Float
|
438
438
|
|
439
439
|
# Represents a unique identifier that is Base64 obfuscated. It is often used to
|
@@ -698,7 +698,7 @@ describe GraphQL::Language::DocumentFromSchemaDefinition do
|
|
698
698
|
}
|
699
699
|
|
700
700
|
# Represents signed double-precision fractional values as specified by [IEEE
|
701
|
-
# 754](
|
701
|
+
# 754](https://en.wikipedia.org/wiki/IEEE_floating_point).
|
702
702
|
scalar Float
|
703
703
|
|
704
704
|
# Represents a unique identifier that is Base64 obfuscated. It is often used to
|
@@ -473,6 +473,18 @@ module Dummy
|
|
473
473
|
def self.resolve_type(type, obj, ctx)
|
474
474
|
Schema.types[obj.class.name.split("::").last]
|
475
475
|
end
|
476
|
+
|
477
|
+
# This is used to confirm that the hook is called:
|
478
|
+
MAGIC_INT_COERCE_VALUE = -1
|
479
|
+
|
480
|
+
def self.type_error(err, ctx)
|
481
|
+
if err.is_a?(GraphQL::IntegerEncodingError) && err.integer_value == 99**99
|
482
|
+
MAGIC_INT_COERCE_VALUE
|
483
|
+
else
|
484
|
+
super
|
485
|
+
end
|
486
|
+
end
|
487
|
+
|
476
488
|
if TESTING_INTERPRETER
|
477
489
|
use GraphQL::Execution::Interpreter
|
478
490
|
end
|
data/spec/support/jazz.rb
CHANGED
@@ -320,10 +320,12 @@ module Jazz
|
|
320
320
|
possible_types Musician, Ensemble
|
321
321
|
|
322
322
|
def self.resolve_type(object, context)
|
323
|
-
|
324
|
-
Ensemble
|
325
|
-
|
326
|
-
|
323
|
+
GraphQL::Execution::Lazy.new do
|
324
|
+
if object.is_a?(Models::Ensemble)
|
325
|
+
Ensemble
|
326
|
+
else
|
327
|
+
Musician
|
328
|
+
end
|
327
329
|
end
|
328
330
|
end
|
329
331
|
end
|
@@ -352,7 +354,7 @@ module Jazz
|
|
352
354
|
def now_playing; Models.data["Ensemble"].first; end
|
353
355
|
|
354
356
|
# For asserting that the object is initialized once:
|
355
|
-
field :object_id,
|
357
|
+
field :object_id, String, null: false
|
356
358
|
field :inspect_context, [String], null: false
|
357
359
|
field :hashyEnsemble, Ensemble, null: false
|
358
360
|
|
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.9.0
|
4
|
+
version: 1.9.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: 2019-02-
|
11
|
+
date: 2019-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: benchmark-ips
|
@@ -437,6 +437,7 @@ files:
|
|
437
437
|
- lib/graphql/id_type.rb
|
438
438
|
- lib/graphql/input_object_type.rb
|
439
439
|
- lib/graphql/int_type.rb
|
440
|
+
- lib/graphql/integer_encoding_error.rb
|
440
441
|
- lib/graphql/interface_type.rb
|
441
442
|
- lib/graphql/internal_representation.rb
|
442
443
|
- lib/graphql/internal_representation/document.rb
|
@@ -986,7 +987,7 @@ files:
|
|
986
987
|
- spec/support/skylight.rb
|
987
988
|
- spec/support/star_wars/schema.rb
|
988
989
|
- spec/support/static_validation_helpers.rb
|
989
|
-
homepage:
|
990
|
+
homepage: https://github.com/rmosolgo/graphql-ruby
|
990
991
|
licenses:
|
991
992
|
- MIT
|
992
993
|
metadata: {}
|
@@ -1001,9 +1002,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
1001
1002
|
version: 2.2.0
|
1002
1003
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
1003
1004
|
requirements:
|
1004
|
-
- - "
|
1005
|
+
- - ">="
|
1005
1006
|
- !ruby/object:Gem::Version
|
1006
|
-
version:
|
1007
|
+
version: '0'
|
1007
1008
|
requirements: []
|
1008
1009
|
rubyforge_project:
|
1009
1010
|
rubygems_version: 2.6.13
|