graphql 1.3.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/graphql/base_type.rb +33 -5
- data/lib/graphql/boolean_type.rb +1 -0
- data/lib/graphql/compatibility/execution_specification.rb +1 -1
- data/lib/graphql/compatibility/execution_specification/specification_schema.rb +1 -0
- data/lib/graphql/directive.rb +10 -2
- data/lib/graphql/directive/deprecated_directive.rb +1 -0
- data/lib/graphql/directive/include_directive.rb +1 -0
- data/lib/graphql/directive/skip_directive.rb +1 -0
- data/lib/graphql/enum_type.rb +1 -0
- data/lib/graphql/execution/execute.rb +1 -13
- data/lib/graphql/float_type.rb +1 -0
- data/lib/graphql/id_type.rb +1 -0
- data/lib/graphql/input_object_type.rb +12 -2
- data/lib/graphql/int_type.rb +1 -0
- data/lib/graphql/interface_type.rb +1 -0
- data/lib/graphql/introspection/directive_location_enum.rb +1 -0
- data/lib/graphql/introspection/directive_type.rb +1 -0
- data/lib/graphql/introspection/enum_value_type.rb +1 -0
- data/lib/graphql/introspection/field_type.rb +1 -0
- data/lib/graphql/introspection/input_fields_field.rb +1 -1
- data/lib/graphql/introspection/input_value_type.rb +1 -0
- data/lib/graphql/introspection/schema_type.rb +2 -0
- data/lib/graphql/introspection/type_kind_enum.rb +1 -0
- data/lib/graphql/introspection/type_type.rb +1 -0
- data/lib/graphql/list_type.rb +1 -0
- data/lib/graphql/non_null_type.rb +1 -0
- data/lib/graphql/object_type.rb +1 -0
- data/lib/graphql/query.rb +50 -13
- data/lib/graphql/query/context.rb +5 -4
- data/lib/graphql/query/serial_execution/field_resolution.rb +1 -22
- data/lib/graphql/relay/array_connection.rb +3 -1
- data/lib/graphql/relay/connection_type.rb +15 -1
- data/lib/graphql/relay/node.rb +1 -0
- data/lib/graphql/relay/page_info.rb +1 -0
- data/lib/graphql/relay/relation_connection.rb +2 -0
- data/lib/graphql/schema.rb +21 -13
- data/lib/graphql/schema/catchall_middleware.rb +2 -2
- data/lib/graphql/schema/middleware_chain.rb +71 -13
- data/lib/graphql/schema/null_mask.rb +10 -0
- data/lib/graphql/schema/printer.rb +85 -59
- data/lib/graphql/schema/rescue_middleware.rb +2 -2
- data/lib/graphql/schema/timeout_middleware.rb +2 -2
- data/lib/graphql/schema/validation.rb +1 -12
- data/lib/graphql/schema/warden.rb +48 -24
- data/lib/graphql/static_validation/literal_validator.rb +2 -2
- data/lib/graphql/string_type.rb +1 -0
- data/lib/graphql/union_type.rb +7 -1
- data/lib/graphql/version.rb +1 -1
- data/readme.md +0 -19
- data/spec/graphql/directive/skip_directive_spec.rb +8 -0
- data/spec/graphql/directive_spec.rb +9 -3
- data/spec/graphql/input_object_type_spec.rb +67 -0
- data/spec/graphql/query/variables_spec.rb +1 -1
- data/spec/graphql/relay/array_connection_spec.rb +9 -0
- data/spec/graphql/relay/connection_type_spec.rb +20 -0
- data/spec/graphql/relay/node_spec.rb +6 -0
- data/spec/graphql/relay/page_info_spec.rb +4 -0
- data/spec/graphql/relay/relation_connection_spec.rb +8 -0
- data/spec/graphql/scalar_type_spec.rb +4 -0
- data/spec/graphql/schema/middleware_chain_spec.rb +27 -13
- data/spec/graphql/schema/printer_spec.rb +121 -6
- data/spec/graphql/schema/rescue_middleware_spec.rb +4 -4
- data/spec/graphql/schema/warden_spec.rb +16 -12
- data/spec/graphql/schema_spec.rb +9 -0
- data/spec/graphql/string_type_spec.rb +10 -4
- data/spec/spec_helper.rb +2 -1
- data/spec/support/star_wars_schema.rb +2 -2
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 54eddb1e7e7ebdbe1ada0ab8286bda07a4141ebc
|
4
|
+
data.tar.gz: d9cc5078d078b0d9d8eded46a17ae224d33b738c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f918ba8ec64d8e3157d454ef76002b4087644fcb1f92a50821f5fd189f40806b4daec24d27049c022a59c27dc9a698742ad099546ce53b20645a7e0f6ebd8c28
|
7
|
+
data.tar.gz: 21140eaea9b18fd8405cb195f67d8f380d08dbf7d537e191c4672bd65240b1f589074927e0a62951f6506eaf0762efcd351e35b0e7951c4012b3552d70b747e0
|
data/lib/graphql/base_type.rb
CHANGED
@@ -4,12 +4,22 @@ module GraphQL
|
|
4
4
|
class BaseType
|
5
5
|
include GraphQL::Define::NonNullWithBang
|
6
6
|
include GraphQL::Define::InstanceDefinable
|
7
|
-
accepts_definitions :name, :description,
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
accepts_definitions :name, :description,
|
8
|
+
:introspection,
|
9
|
+
:default_scalar,
|
10
|
+
:default_relay,
|
11
|
+
{
|
12
|
+
connection: GraphQL::Define::AssignConnection,
|
13
|
+
global_id_field: GraphQL::Define::AssignGlobalIdField,
|
14
|
+
}
|
11
15
|
|
12
|
-
ensure_defined(:name, :description)
|
16
|
+
ensure_defined(:name, :description, :introspection?, :default_scalar?)
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@introspection = false
|
20
|
+
@default_scalar = false
|
21
|
+
@default_relay = false
|
22
|
+
end
|
13
23
|
|
14
24
|
def initialize_copy(other)
|
15
25
|
super
|
@@ -24,6 +34,24 @@ module GraphQL
|
|
24
34
|
# @return [String, nil] a description for this type
|
25
35
|
attr_accessor :description
|
26
36
|
|
37
|
+
# @return [Boolean] Is this type a predefined introspection type?
|
38
|
+
def introspection?
|
39
|
+
@introspection
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [Boolean] Is this type a built-in scalar type? (eg, `String`, `Int`)
|
43
|
+
def default_scalar?
|
44
|
+
@default_scalar
|
45
|
+
end
|
46
|
+
|
47
|
+
# @return [Boolean] Is this type a built-in Relay type? (`Node`, `PageInfo`)
|
48
|
+
def default_relay?
|
49
|
+
@default_relay
|
50
|
+
end
|
51
|
+
|
52
|
+
# @api private
|
53
|
+
attr_writer :introspection, :default_scalar, :default_relay
|
54
|
+
|
27
55
|
# @param other [GraphQL::BaseType] compare to this object
|
28
56
|
# @return [Boolean] are these types equivalent? (incl. non-null, list)
|
29
57
|
def ==(other)
|
data/lib/graphql/boolean_type.rb
CHANGED
@@ -49,6 +49,7 @@ module GraphQL
|
|
49
49
|
end
|
50
50
|
|
51
51
|
module TestMiddleware
|
52
|
+
# TODO: Once deprecated `next_middleware` argument becomes unsupported, add `&` to the argument
|
52
53
|
def self.call(parent_type, parent_object, field_definition, field_args, query_context, next_middleware)
|
53
54
|
query_context[:middleware_log] && query_context[:middleware_log] << field_definition.name
|
54
55
|
next_middleware.call
|
data/lib/graphql/directive.rb
CHANGED
@@ -8,10 +8,12 @@ module GraphQL
|
|
8
8
|
#
|
9
9
|
class Directive
|
10
10
|
include GraphQL::Define::InstanceDefinable
|
11
|
-
accepts_definitions :locations, :name, :description, :arguments, argument: GraphQL::Define::AssignArgument
|
11
|
+
accepts_definitions :locations, :name, :description, :arguments, :default_directive, argument: GraphQL::Define::AssignArgument
|
12
12
|
|
13
13
|
attr_accessor :locations, :arguments, :name, :description
|
14
|
-
|
14
|
+
# @api private
|
15
|
+
attr_writer :default_directive
|
16
|
+
ensure_defined(:locations, :arguments, :name, :description, :default_directive?)
|
15
17
|
|
16
18
|
LOCATIONS = [
|
17
19
|
QUERY = :QUERY,
|
@@ -58,6 +60,7 @@ module GraphQL
|
|
58
60
|
|
59
61
|
def initialize
|
60
62
|
@arguments = {}
|
63
|
+
@default_directive = false
|
61
64
|
end
|
62
65
|
|
63
66
|
def to_s
|
@@ -75,6 +78,11 @@ module GraphQL
|
|
75
78
|
def on_operation?
|
76
79
|
locations.include?(QUERY) && locations.include?(MUTATION) && locations.include?(SUBSCRIPTION)
|
77
80
|
end
|
81
|
+
|
82
|
+
# @return [Boolean] Is this directive supplied by default? (eg `@skip`)
|
83
|
+
def default_directive?
|
84
|
+
@default_directive
|
85
|
+
end
|
78
86
|
end
|
79
87
|
end
|
80
88
|
|
@@ -9,4 +9,5 @@ GraphQL::Directive::DeprecatedDirective = GraphQL::Directive.define do
|
|
9
9
|
"in [Markdown](https://daringfireball.net/projects/markdown/)."
|
10
10
|
|
11
11
|
argument :reason, GraphQL::STRING_TYPE, reason_description, default_value: GraphQL::Directive::DEFAULT_DEPRECATION_REASON
|
12
|
+
default_directive true
|
12
13
|
end
|
@@ -4,4 +4,5 @@ GraphQL::Directive::IncludeDirective = GraphQL::Directive.define do
|
|
4
4
|
description "Directs the executor to include this field or fragment only when the `if` argument is true."
|
5
5
|
locations([GraphQL::Directive::FIELD, GraphQL::Directive::FRAGMENT_SPREAD, GraphQL::Directive::INLINE_FRAGMENT])
|
6
6
|
argument :if, !GraphQL::BOOLEAN_TYPE, 'Included when true.'
|
7
|
+
default_directive true
|
7
8
|
end
|
data/lib/graphql/enum_type.rb
CHANGED
@@ -57,20 +57,8 @@ module GraphQL
|
|
57
57
|
)
|
58
58
|
|
59
59
|
arguments = query.arguments_for(selection.irep_node, field)
|
60
|
-
middlewares = query.schema.middleware
|
61
|
-
resolve_arguments = [parent_type, object, field, arguments, field_ctx]
|
62
|
-
|
63
60
|
raw_value = begin
|
64
|
-
|
65
|
-
if middlewares.any?
|
66
|
-
chain = GraphQL::Schema::MiddlewareChain.new(
|
67
|
-
steps: middlewares + [FieldResolveStep],
|
68
|
-
arguments: resolve_arguments
|
69
|
-
)
|
70
|
-
chain.call
|
71
|
-
else
|
72
|
-
FieldResolveStep.call(*resolve_arguments)
|
73
|
-
end
|
61
|
+
query_ctx.schema.middleware.invoke([parent_type, object, field, arguments, field_ctx])
|
74
62
|
rescue GraphQL::ExecutionError => err
|
75
63
|
err
|
76
64
|
end
|
data/lib/graphql/float_type.rb
CHANGED
data/lib/graphql/id_type.rb
CHANGED
@@ -42,6 +42,7 @@ module GraphQL
|
|
42
42
|
|
43
43
|
|
44
44
|
def initialize
|
45
|
+
super
|
45
46
|
@arguments = {}
|
46
47
|
end
|
47
48
|
|
@@ -57,7 +58,16 @@ module GraphQL
|
|
57
58
|
def validate_non_null_input(input, warden)
|
58
59
|
result = GraphQL::Query::InputValidationResult.new
|
59
60
|
|
60
|
-
|
61
|
+
if (input.to_h rescue nil).nil?
|
62
|
+
result.add_problem(
|
63
|
+
"Expected #{JSON.generate(input, quirks_mode: true)} to be a key, value object " \
|
64
|
+
" responding to `to_h`."
|
65
|
+
)
|
66
|
+
return result
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
visible_arguments_map = warden.arguments(self).reduce({}) { |m, f| m[f.name] = f; m}
|
61
71
|
|
62
72
|
# Items in the input that are unexpected
|
63
73
|
input.each do |name, value|
|
@@ -67,7 +77,7 @@ module GraphQL
|
|
67
77
|
end
|
68
78
|
|
69
79
|
# Items in the input that are expected, but have invalid values
|
70
|
-
|
80
|
+
visible_arguments_map.map do |name, field|
|
71
81
|
field_result = field.type.validate_input(input[name], warden)
|
72
82
|
if !field_result.valid?
|
73
83
|
result.merge_result!(name, field_result)
|
data/lib/graphql/int_type.rb
CHANGED
@@ -14,4 +14,5 @@ GraphQL::Introspection::DirectiveType = GraphQL::ObjectType.define do
|
|
14
14
|
field :onOperation, !types.Boolean, deprecation_reason: "Use `locations`.", property: :on_operation?
|
15
15
|
field :onFragment, !types.Boolean, deprecation_reason: "Use `locations`.", property: :on_fragment?
|
16
16
|
field :onField, !types.Boolean, deprecation_reason: "Use `locations`.", property: :on_field?
|
17
|
+
introspection true
|
17
18
|
end
|
@@ -4,7 +4,7 @@ GraphQL::Introspection::InputFieldsField = GraphQL::Field.define do
|
|
4
4
|
type types[!GraphQL::Introspection::InputValueType]
|
5
5
|
resolve ->(target, a, ctx) {
|
6
6
|
if target.kind.input_object?
|
7
|
-
ctx.warden.
|
7
|
+
ctx.warden.arguments(target)
|
8
8
|
else
|
9
9
|
nil
|
10
10
|
end
|
@@ -24,4 +24,6 @@ GraphQL::Introspection::SchemaType = GraphQL::ObjectType.define do
|
|
24
24
|
field :directives, !types[!GraphQL::Introspection::DirectiveType], "A list of all directives supported by this server." do
|
25
25
|
resolve ->(obj, arg, ctx) { obj.directives.values }
|
26
26
|
end
|
27
|
+
|
28
|
+
introspection true
|
27
29
|
end
|
@@ -22,4 +22,5 @@ GraphQL::Introspection::TypeType = GraphQL::ObjectType.define do
|
|
22
22
|
field :enumValues, GraphQL::Introspection::EnumValuesField
|
23
23
|
field :inputFields, GraphQL::Introspection::InputFieldsField
|
24
24
|
field :ofType, GraphQL::Introspection::OfTypeField
|
25
|
+
introspection true
|
25
26
|
end
|
data/lib/graphql/list_type.rb
CHANGED
data/lib/graphql/object_type.rb
CHANGED
data/lib/graphql/query.rb
CHANGED
@@ -18,14 +18,6 @@ module GraphQL
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
module NullExcept
|
22
|
-
module_function
|
23
|
-
|
24
|
-
def call(member)
|
25
|
-
false
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
21
|
attr_reader :schema, :document, :context, :fragments, :operations, :root_value, :max_depth, :query_string, :warden, :provided_variables
|
30
22
|
|
31
23
|
# Prepare query `query_string` on `schema`
|
@@ -38,11 +30,19 @@ module GraphQL
|
|
38
30
|
# @param max_depth [Numeric] the maximum number of nested selections allowed for this query (falls back to schema-level value)
|
39
31
|
# @param max_complexity [Numeric] the maximum field complexity for this query (falls back to schema-level value)
|
40
32
|
# @param except [<#call(schema_member)>] If provided, objects will be hidden from the schema when `.call(schema_member)` returns truthy
|
41
|
-
def initialize(schema, query_string = nil, document: nil, context: nil, variables: {}, validate: true, operation_name: nil, root_value: nil, max_depth: nil, max_complexity: nil, except:
|
33
|
+
def initialize(schema, query_string = nil, document: nil, context: nil, variables: {}, validate: true, operation_name: nil, root_value: nil, max_depth: nil, max_complexity: nil, except: nil, only: nil)
|
42
34
|
fail ArgumentError, "a query string or document is required" unless query_string || document
|
43
35
|
|
44
36
|
@schema = schema
|
45
|
-
|
37
|
+
mask = if except
|
38
|
+
wrap_if_legacy_mask(except)
|
39
|
+
elsif only
|
40
|
+
InvertedMask.new(wrap_if_legacy_mask(only))
|
41
|
+
else
|
42
|
+
schema.default_mask
|
43
|
+
end
|
44
|
+
@context = Context.new(query: self, values: context)
|
45
|
+
@warden = GraphQL::Schema::Warden.new(mask, schema: @schema, context: @context)
|
46
46
|
@max_depth = max_depth || schema.max_depth
|
47
47
|
@max_complexity = max_complexity || schema.max_complexity
|
48
48
|
@query_analyzers = schema.query_analyzers.dup
|
@@ -52,7 +52,6 @@ module GraphQL
|
|
52
52
|
if @max_complexity
|
53
53
|
@query_analyzers << GraphQL::Analysis::MaxQueryComplexity.new(@max_complexity)
|
54
54
|
end
|
55
|
-
@context = Context.new(query: self, values: context)
|
56
55
|
@root_value = root_value
|
57
56
|
@operation_name = operation_name
|
58
57
|
@fragments = {}
|
@@ -74,6 +73,8 @@ module GraphQL
|
|
74
73
|
end
|
75
74
|
end
|
76
75
|
|
76
|
+
@resolved_types_cache = Hash.new { |h, k| h[k] = @schema.resolve_type(k, @context) }
|
77
|
+
|
77
78
|
@arguments_cache = Hash.new { |h, k| h[k] = {} }
|
78
79
|
@validation_errors = []
|
79
80
|
@analysis_errors = []
|
@@ -214,8 +215,11 @@ module GraphQL
|
|
214
215
|
@warden.possible_types(type)
|
215
216
|
end
|
216
217
|
|
217
|
-
|
218
|
-
|
218
|
+
# @param value [Object] Any runtime value
|
219
|
+
# @return [GraphQL::ObjectType, nil] The runtime type of `value` from {Schema#resolve_type}
|
220
|
+
# @see {#possible_types} to apply filtering from `only` / `except`
|
221
|
+
def resolve_type(value)
|
222
|
+
@resolved_types_cache[value]
|
219
223
|
end
|
220
224
|
|
221
225
|
def mutation?
|
@@ -257,5 +261,38 @@ module GraphQL
|
|
257
261
|
operations[operation_name]
|
258
262
|
end
|
259
263
|
end
|
264
|
+
|
265
|
+
def wrap_if_legacy_mask(mask)
|
266
|
+
if (mask.is_a?(Proc) && mask.arity == 1) || mask.method(:call).arity == 1
|
267
|
+
warn("Schema.execute(..., except:) filters now accept two arguments, `(member, ctx)`. One-argument filters are deprecated.")
|
268
|
+
LegacyMaskWrap.new(mask)
|
269
|
+
else
|
270
|
+
mask
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
# @api private
|
275
|
+
class InvertedMask
|
276
|
+
def initialize(inner_mask)
|
277
|
+
@inner_mask = inner_mask
|
278
|
+
end
|
279
|
+
|
280
|
+
# Returns true when the inner mask returned false
|
281
|
+
# Returns false when the inner mask returned true
|
282
|
+
def call(member, ctx)
|
283
|
+
!@inner_mask.call(member, ctx)
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
# @api private
|
288
|
+
class LegacyMaskWrap
|
289
|
+
def initialize(inner_mask)
|
290
|
+
@inner_mask = inner_mask
|
291
|
+
end
|
292
|
+
|
293
|
+
def call(member, ctx)
|
294
|
+
@inner_mask.call(member)
|
295
|
+
end
|
296
|
+
end
|
260
297
|
end
|
261
298
|
end
|
@@ -32,9 +32,6 @@ module GraphQL
|
|
32
32
|
# @return [GraphQL::Schema]
|
33
33
|
attr_reader :schema
|
34
34
|
|
35
|
-
# @return [GraphQL::Schema::Mask::Warden]
|
36
|
-
attr_reader :warden
|
37
|
-
|
38
35
|
# @return [Array<String, Integer>] The current position in the result
|
39
36
|
attr_reader :path
|
40
37
|
|
@@ -46,7 +43,6 @@ module GraphQL
|
|
46
43
|
@schema = query.schema
|
47
44
|
@values = values || {}
|
48
45
|
@errors = []
|
49
|
-
@warden = query.warden
|
50
46
|
@path = []
|
51
47
|
end
|
52
48
|
|
@@ -55,6 +51,11 @@ module GraphQL
|
|
55
51
|
@values[key]
|
56
52
|
end
|
57
53
|
|
54
|
+
# @return [GraphQL::Schema::Warden]
|
55
|
+
def warden
|
56
|
+
@warden ||= @query.warden
|
57
|
+
end
|
58
|
+
|
58
59
|
# Reassign `key` to the hash passed to {Schema#execute} as `context:`
|
59
60
|
def []=(key, value)
|
60
61
|
@values[key] = value
|