graphql 1.9.7 → 1.9.8
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/generators/graphql/install_generator.rb +2 -1
- data/lib/generators/graphql/templates/base_argument.erb +4 -0
- data/lib/generators/graphql/templates/base_field.erb +2 -0
- data/lib/generators/graphql/templates/base_input_object.erb +1 -0
- data/lib/graphql/analysis/ast/query_complexity.rb +34 -18
- data/lib/graphql/argument.rb +8 -2
- data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +1 -1
- data/lib/graphql/language/lexer.rb +24 -13
- data/lib/graphql/language/lexer.rl +23 -13
- data/lib/graphql/query/arguments.rb +16 -15
- data/lib/graphql/schema.rb +105 -48
- data/lib/graphql/schema/argument.rb +12 -1
- data/lib/graphql/schema/build_from_definition.rb +3 -0
- data/lib/graphql/schema/field.rb +3 -8
- data/lib/graphql/schema/find_inherited_value.rb +20 -0
- data/lib/graphql/schema/input_object.rb +1 -3
- data/lib/graphql/schema/loader.rb +1 -0
- data/lib/graphql/schema/member/base_dsl_methods.rb +7 -18
- data/lib/graphql/schema/member/has_arguments.rb +4 -9
- data/lib/graphql/schema/member/has_fields.rb +14 -0
- data/lib/graphql/schema/member/relay_shortcuts.rb +2 -2
- data/lib/graphql/schema/resolver.rb +31 -8
- data/lib/graphql/schema/resolver/has_payload_type.rb +3 -2
- data/lib/graphql/schema/subscription.rb +1 -1
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/spec/graphql/analysis/analyze_query_spec.rb +14 -25
- data/spec/graphql/analysis/ast/max_query_complexity_spec.rb +7 -19
- data/spec/graphql/analysis/ast/max_query_depth_spec.rb +5 -12
- data/spec/graphql/analysis/max_query_complexity_spec.rb +12 -20
- data/spec/graphql/analysis/max_query_depth_spec.rb +6 -13
- data/spec/graphql/language/lexer_spec.rb +19 -1
- data/spec/graphql/schema/argument_spec.rb +1 -1
- data/spec/graphql/schema/build_from_definition_spec.rb +10 -0
- data/spec/graphql/schema/catchall_middleware_spec.rb +6 -9
- data/spec/graphql/schema/input_object_spec.rb +25 -0
- data/spec/graphql/schema/loader_spec.rb +65 -1
- data/spec/graphql/schema/object_spec.rb +21 -0
- data/spec/graphql/schema/resolver_spec.rb +30 -1
- data/spec/graphql/schema_spec.rb +135 -0
- data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +25 -0
- data/spec/integration/rails/generators/graphql/install_generator_spec.rb +20 -0
- data/spec/integration/tmp/app/graphql/types/page_type.rb +5 -0
- data/spec/support/dummy/schema.rb +1 -1
- data/spec/support/lazy_helpers.rb +1 -1
- data/spec/support/parser/filename_example_invalid_utf8.graphql +1 -0
- metadata +10 -132
- data/spec/integration/tmp/app/graphql/types/date_type.rb +0 -14
- data/spec/integration/tmp/dummy/Gemfile +0 -50
- data/spec/integration/tmp/dummy/README.md +0 -24
- data/spec/integration/tmp/dummy/Rakefile +0 -6
- data/spec/integration/tmp/dummy/app/assets/config/manifest.js +0 -3
- data/spec/integration/tmp/dummy/app/assets/javascripts/application.js +0 -16
- data/spec/integration/tmp/dummy/app/assets/javascripts/cable.js +0 -13
- data/spec/integration/tmp/dummy/app/assets/stylesheets/application.css +0 -15
- data/spec/integration/tmp/dummy/app/channels/application_cable/channel.rb +0 -5
- data/spec/integration/tmp/dummy/app/channels/application_cable/connection.rb +0 -5
- data/spec/integration/tmp/dummy/app/controllers/application_controller.rb +0 -4
- data/spec/integration/tmp/dummy/app/controllers/graphql_controller.rb +0 -44
- data/spec/integration/tmp/dummy/app/helpers/application_helper.rb +0 -3
- data/spec/integration/tmp/dummy/app/jobs/application_job.rb +0 -3
- data/spec/integration/tmp/dummy/app/mailers/application_mailer.rb +0 -5
- data/spec/integration/tmp/dummy/app/mydirectory/dummy_schema.rb +0 -5
- data/spec/integration/tmp/dummy/app/mydirectory/mutations/update_name.rb +0 -15
- data/spec/integration/tmp/dummy/app/mydirectory/types/base_enum.rb +0 -5
- data/spec/integration/tmp/dummy/app/mydirectory/types/base_input_object.rb +0 -5
- data/spec/integration/tmp/dummy/app/mydirectory/types/base_interface.rb +0 -6
- data/spec/integration/tmp/dummy/app/mydirectory/types/base_object.rb +0 -5
- data/spec/integration/tmp/dummy/app/mydirectory/types/base_scalar.rb +0 -5
- data/spec/integration/tmp/dummy/app/mydirectory/types/base_union.rb +0 -5
- data/spec/integration/tmp/dummy/app/mydirectory/types/mutation_type.rb +0 -12
- data/spec/integration/tmp/dummy/app/mydirectory/types/query_type.rb +0 -14
- data/spec/integration/tmp/dummy/app/views/layouts/application.html.erb +0 -14
- data/spec/integration/tmp/dummy/app/views/layouts/mailer.html.erb +0 -13
- data/spec/integration/tmp/dummy/app/views/layouts/mailer.text.erb +0 -1
- data/spec/integration/tmp/dummy/bin/bundle +0 -3
- data/spec/integration/tmp/dummy/bin/rails +0 -4
- data/spec/integration/tmp/dummy/bin/rake +0 -4
- data/spec/integration/tmp/dummy/bin/setup +0 -34
- data/spec/integration/tmp/dummy/bin/update +0 -29
- data/spec/integration/tmp/dummy/config.ru +0 -5
- data/spec/integration/tmp/dummy/config/application.rb +0 -26
- data/spec/integration/tmp/dummy/config/boot.rb +0 -4
- data/spec/integration/tmp/dummy/config/cable.yml +0 -9
- data/spec/integration/tmp/dummy/config/environment.rb +0 -6
- data/spec/integration/tmp/dummy/config/environments/development.rb +0 -52
- data/spec/integration/tmp/dummy/config/environments/production.rb +0 -84
- data/spec/integration/tmp/dummy/config/environments/test.rb +0 -43
- data/spec/integration/tmp/dummy/config/initializers/application_controller_renderer.rb +0 -9
- data/spec/integration/tmp/dummy/config/initializers/assets.rb +0 -12
- data/spec/integration/tmp/dummy/config/initializers/backtrace_silencers.rb +0 -8
- data/spec/integration/tmp/dummy/config/initializers/cookies_serializer.rb +0 -6
- data/spec/integration/tmp/dummy/config/initializers/filter_parameter_logging.rb +0 -5
- data/spec/integration/tmp/dummy/config/initializers/inflections.rb +0 -17
- data/spec/integration/tmp/dummy/config/initializers/mime_types.rb +0 -5
- data/spec/integration/tmp/dummy/config/initializers/new_framework_defaults.rb +0 -24
- data/spec/integration/tmp/dummy/config/initializers/session_store.rb +0 -4
- data/spec/integration/tmp/dummy/config/initializers/wrap_parameters.rb +0 -10
- data/spec/integration/tmp/dummy/config/locales/en.yml +0 -23
- data/spec/integration/tmp/dummy/config/puma.rb +0 -48
- data/spec/integration/tmp/dummy/config/routes.rb +0 -9
- data/spec/integration/tmp/dummy/config/secrets.yml +0 -22
- data/spec/integration/tmp/dummy/db/seeds.rb +0 -8
- data/spec/integration/tmp/dummy/log/test.log +0 -0
- data/spec/integration/tmp/dummy/public/404.html +0 -67
- data/spec/integration/tmp/dummy/public/422.html +0 -67
- data/spec/integration/tmp/dummy/public/500.html +0 -66
- data/spec/integration/tmp/dummy/public/apple-touch-icon-precomposed.png +0 -0
- data/spec/integration/tmp/dummy/public/apple-touch-icon.png +0 -0
- data/spec/integration/tmp/dummy/public/favicon.ico +0 -0
- data/spec/integration/tmp/dummy/public/robots.txt +0 -5
- data/spec/integration/tmp/dummy/test/test_helper.rb +0 -8
|
@@ -24,6 +24,11 @@ module GraphQL
|
|
|
24
24
|
# @return [Class, Module, nil] If this argument should load an application object, this is the type of object to load
|
|
25
25
|
attr_reader :loads
|
|
26
26
|
|
|
27
|
+
# @return [Boolean] true if a resolver defined this argument
|
|
28
|
+
def from_resolver?
|
|
29
|
+
@from_resolver
|
|
30
|
+
end
|
|
31
|
+
|
|
27
32
|
# @param arg_name [Symbol]
|
|
28
33
|
# @param type_expr
|
|
29
34
|
# @param desc [String]
|
|
@@ -33,7 +38,9 @@ module GraphQL
|
|
|
33
38
|
# @param as [Symbol] Override the keyword name when passed to a method
|
|
34
39
|
# @param prepare [Symbol] A method to call to transform this argument's valuebefore sending it to field resolution
|
|
35
40
|
# @param camelize [Boolean] if true, the name will be camelized when building the schema
|
|
36
|
-
|
|
41
|
+
# @param from_resolver [Boolean] if true, a Resolver class defined this argument
|
|
42
|
+
# @param method_access [Boolean] If false, don't build method access on legacy {Query::Arguments} instances.
|
|
43
|
+
def initialize(arg_name = nil, type_expr = nil, desc = nil, required:, type: nil, name: nil, loads: nil, description: nil, ast_node: nil, default_value: NO_DEFAULT, as: nil, from_resolver: false, camelize: true, prepare: nil, method_access: true, owner:, &definition_block)
|
|
37
44
|
arg_name ||= name
|
|
38
45
|
name_str = camelize ? Member::BuildType.camelize(arg_name.to_s) : arg_name.to_s
|
|
39
46
|
@name = name_str.freeze
|
|
@@ -46,6 +53,9 @@ module GraphQL
|
|
|
46
53
|
@loads = loads
|
|
47
54
|
@keyword = as || Schema::Member::BuildType.underscore(@name).to_sym
|
|
48
55
|
@prepare = prepare
|
|
56
|
+
@ast_node = ast_node
|
|
57
|
+
@from_resolver = from_resolver
|
|
58
|
+
@method_access = method_access
|
|
49
59
|
|
|
50
60
|
if definition_block
|
|
51
61
|
if definition_block.arity == 1
|
|
@@ -94,6 +104,7 @@ module GraphQL
|
|
|
94
104
|
argument.description = @description
|
|
95
105
|
argument.metadata[:type_class] = self
|
|
96
106
|
argument.as = @as
|
|
107
|
+
argument.method_access = @method_access
|
|
97
108
|
if NO_DEFAULT != @default_value
|
|
98
109
|
argument.default_value = @default_value
|
|
99
110
|
end
|
|
@@ -232,6 +232,7 @@ module GraphQL
|
|
|
232
232
|
name: input_argument.name,
|
|
233
233
|
type: type_resolver.call(input_argument.type),
|
|
234
234
|
description: input_argument.description,
|
|
235
|
+
method_access: false,
|
|
235
236
|
**kwargs,
|
|
236
237
|
)
|
|
237
238
|
|
|
@@ -269,6 +270,7 @@ module GraphQL
|
|
|
269
270
|
name: directive_argument.name,
|
|
270
271
|
type: type_resolver.call(directive_argument.type),
|
|
271
272
|
description: directive_argument.description,
|
|
273
|
+
method_access: false,
|
|
272
274
|
**kwargs,
|
|
273
275
|
)
|
|
274
276
|
|
|
@@ -306,6 +308,7 @@ module GraphQL
|
|
|
306
308
|
name: argument.name,
|
|
307
309
|
description: argument.description,
|
|
308
310
|
type: type_resolver.call(argument.type),
|
|
311
|
+
method_access: false,
|
|
309
312
|
**kwargs,
|
|
310
313
|
)
|
|
311
314
|
|
data/lib/graphql/schema/field.rb
CHANGED
|
@@ -205,7 +205,7 @@ module GraphQL
|
|
|
205
205
|
|
|
206
206
|
# TODO: I think non-string/symbol hash keys are wrongly normalized (eg `1` will not work)
|
|
207
207
|
method_name = method || hash_key || @underscored_name
|
|
208
|
-
resolver_method ||= @underscored_name
|
|
208
|
+
resolver_method ||= @underscored_name.to_sym
|
|
209
209
|
|
|
210
210
|
@method_str = method_name.to_s
|
|
211
211
|
@method_sym = method_name.to_sym
|
|
@@ -418,13 +418,10 @@ module GraphQL
|
|
|
418
418
|
end
|
|
419
419
|
|
|
420
420
|
def authorized?(object, context)
|
|
421
|
-
|
|
421
|
+
if @resolver_class
|
|
422
|
+
# The resolver will check itself during `resolve()`
|
|
422
423
|
@resolver_class.authorized?(object, context)
|
|
423
424
|
else
|
|
424
|
-
true
|
|
425
|
-
end
|
|
426
|
-
|
|
427
|
-
if self_auth
|
|
428
425
|
# Faster than `.any?`
|
|
429
426
|
arguments.each_value do |arg|
|
|
430
427
|
if !arg.authorized?(object, context)
|
|
@@ -432,8 +429,6 @@ module GraphQL
|
|
|
432
429
|
end
|
|
433
430
|
end
|
|
434
431
|
true
|
|
435
|
-
else
|
|
436
|
-
false
|
|
437
432
|
end
|
|
438
433
|
end
|
|
439
434
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module GraphQL
|
|
2
|
+
class Schema
|
|
3
|
+
module FindInheritedValue
|
|
4
|
+
private
|
|
5
|
+
|
|
6
|
+
def find_inherited_value(method_name, default_value = nil)
|
|
7
|
+
if self.is_a?(Class)
|
|
8
|
+
superclass.respond_to?(method_name, true) ? superclass.send(method_name) : default_value
|
|
9
|
+
else
|
|
10
|
+
ancestors[1..-1].each do |ancestor|
|
|
11
|
+
if ancestor.respond_to?(method_name, true)
|
|
12
|
+
return ancestor.send(method_name)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
default_value
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -23,7 +23,7 @@ module GraphQL
|
|
|
23
23
|
ruby_kwargs_key = arg_defn.keyword
|
|
24
24
|
loads = arg_defn.loads
|
|
25
25
|
|
|
26
|
-
if @ruby_style_hash.key?(ruby_kwargs_key) && loads
|
|
26
|
+
if @ruby_style_hash.key?(ruby_kwargs_key) && loads && !arg_defn.from_resolver?
|
|
27
27
|
value = @ruby_style_hash[ruby_kwargs_key]
|
|
28
28
|
@ruby_style_hash[ruby_kwargs_key] = if arg_defn.type.list?
|
|
29
29
|
GraphQL::Execution::Lazy.all(value.map { |val| load_application_object(arg_defn, loads, val) })
|
|
@@ -99,8 +99,6 @@ module GraphQL
|
|
|
99
99
|
attr_accessor :arguments_class
|
|
100
100
|
|
|
101
101
|
def argument(*args, **kwargs, &block)
|
|
102
|
-
# Translate `loads:` to `as:` if needed`
|
|
103
|
-
*args, kwargs = argument_with_loads(*args, **kwargs, &block)
|
|
104
102
|
argument_defn = super(*args, **kwargs, &block)
|
|
105
103
|
# Add a method access
|
|
106
104
|
method_name = argument_defn.keyword
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "graphql/schema/find_inherited_value"
|
|
4
|
+
|
|
3
5
|
module GraphQL
|
|
4
6
|
class Schema
|
|
5
7
|
class Member
|
|
@@ -7,6 +9,8 @@ module GraphQL
|
|
|
7
9
|
# @api private
|
|
8
10
|
# @see Classes that extend this, eg {GraphQL::Schema::Object}
|
|
9
11
|
module BaseDSLMethods
|
|
12
|
+
include GraphQL::Schema::FindInheritedValue
|
|
13
|
+
|
|
10
14
|
# Call this with a new name to override the default name for this schema member; OR
|
|
11
15
|
# call it without an argument to get the name of this schema member
|
|
12
16
|
#
|
|
@@ -42,7 +46,7 @@ module GraphQL
|
|
|
42
46
|
if new_description
|
|
43
47
|
@description = new_description
|
|
44
48
|
else
|
|
45
|
-
@description ||
|
|
49
|
+
@description || find_inherited_value(:description)
|
|
46
50
|
end
|
|
47
51
|
end
|
|
48
52
|
|
|
@@ -51,7 +55,7 @@ module GraphQL
|
|
|
51
55
|
if !new_introspection.nil?
|
|
52
56
|
@introspection = new_introspection
|
|
53
57
|
else
|
|
54
|
-
@introspection ||
|
|
58
|
+
@introspection || find_inherited_value(:introspection, false)
|
|
55
59
|
end
|
|
56
60
|
end
|
|
57
61
|
|
|
@@ -76,7 +80,7 @@ module GraphQL
|
|
|
76
80
|
alias :unwrap :itself
|
|
77
81
|
|
|
78
82
|
def overridden_graphql_name
|
|
79
|
-
@graphql_name ||
|
|
83
|
+
@graphql_name || find_inherited_value(:overridden_graphql_name)
|
|
80
84
|
end
|
|
81
85
|
|
|
82
86
|
# Creates the default name for a schema member.
|
|
@@ -113,21 +117,6 @@ module GraphQL
|
|
|
113
117
|
true
|
|
114
118
|
end
|
|
115
119
|
end
|
|
116
|
-
|
|
117
|
-
private
|
|
118
|
-
|
|
119
|
-
def find_inherited_method(method_name, default_value)
|
|
120
|
-
if self.is_a?(Class)
|
|
121
|
-
superclass.respond_to?(method_name) ? superclass.public_send(method_name) : default_value
|
|
122
|
-
else
|
|
123
|
-
ancestors[1..-1].each do |ancestor|
|
|
124
|
-
if ancestor.respond_to?(method_name)
|
|
125
|
-
return ancestor.public_send(method_name)
|
|
126
|
-
end
|
|
127
|
-
end
|
|
128
|
-
default_value
|
|
129
|
-
end
|
|
130
|
-
end
|
|
131
120
|
end
|
|
132
121
|
end
|
|
133
122
|
end
|
|
@@ -13,7 +13,10 @@ module GraphQL
|
|
|
13
13
|
cls.include(ArgumentObjectLoader)
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
# @see {GraphQL::Schema::Argument#initialize} for parameters
|
|
17
|
+
# @return [GraphQL::Schema::Argument] An instance of {arguments_class}, created from `*args`
|
|
18
|
+
def argument(*args, **kwargs, &block)
|
|
19
|
+
kwargs[:owner] = self
|
|
17
20
|
loads = kwargs[:loads]
|
|
18
21
|
if loads
|
|
19
22
|
name = args[0]
|
|
@@ -32,14 +35,6 @@ module GraphQL
|
|
|
32
35
|
|
|
33
36
|
kwargs[:as] ||= inferred_arg_name
|
|
34
37
|
end
|
|
35
|
-
|
|
36
|
-
return [*args, **kwargs]
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
# @see {GraphQL::Schema::Argument#initialize} for parameters
|
|
40
|
-
# @return [GraphQL::Schema::Argument] An instance of {arguments_class}, created from `*args`
|
|
41
|
-
def argument(*args, **kwargs, &block)
|
|
42
|
-
kwargs[:owner] = self
|
|
43
38
|
arg_defn = self.argument_class.new(*args, **kwargs, &block)
|
|
44
39
|
add_argument(arg_defn)
|
|
45
40
|
end
|
|
@@ -38,10 +38,24 @@ module GraphQL
|
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
+
# A list of field names that we should advise users to pick a different
|
|
42
|
+
# resolve method name.
|
|
43
|
+
#
|
|
44
|
+
# @api private
|
|
45
|
+
CONFLICT_FIELD_NAMES = Set.new([
|
|
46
|
+
# GraphQL-Ruby conflicts
|
|
47
|
+
:context, :object,
|
|
48
|
+
# Ruby built-ins conflicts
|
|
49
|
+
:method, :class
|
|
50
|
+
])
|
|
51
|
+
|
|
41
52
|
# Register this field with the class, overriding a previous one if needed.
|
|
42
53
|
# @param field_defn [GraphQL::Schema::Field]
|
|
43
54
|
# @return [void]
|
|
44
55
|
def add_field(field_defn)
|
|
56
|
+
if CONFLICT_FIELD_NAMES.include?(field_defn.resolver_method)
|
|
57
|
+
warn "#{self.graphql_name}'s `field :#{field_defn.name}` conflicts with a built-in method, use `resolver_method:` to pick a different resolver method for this field (for example, `resolver_method: :resolve_#{field_defn.resolver_method}` and `def resolve_#{field_defn.resolver_method}`)"
|
|
58
|
+
end
|
|
45
59
|
own_fields[field_defn.name] = field_defn
|
|
46
60
|
nil
|
|
47
61
|
end
|
|
@@ -8,7 +8,7 @@ module GraphQL
|
|
|
8
8
|
if new_edge_type_class
|
|
9
9
|
@edge_type_class = new_edge_type_class
|
|
10
10
|
else
|
|
11
|
-
@edge_type_class ||
|
|
11
|
+
@edge_type_class || find_inherited_value(:edge_type_class, Types::Relay::BaseEdge)
|
|
12
12
|
end
|
|
13
13
|
end
|
|
14
14
|
|
|
@@ -16,7 +16,7 @@ module GraphQL
|
|
|
16
16
|
if new_connection_type_class
|
|
17
17
|
@connection_type_class = new_connection_type_class
|
|
18
18
|
else
|
|
19
|
-
@connection_type_class ||
|
|
19
|
+
@connection_type_class || find_inherited_value(:connection_type_class, Types::Relay::BaseConnection)
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
|
|
@@ -123,12 +123,36 @@ module GraphQL
|
|
|
123
123
|
# Called after arguments are loaded, but before resolving.
|
|
124
124
|
#
|
|
125
125
|
# Override it to check everything before calling the mutation.
|
|
126
|
-
# @param
|
|
126
|
+
# @param inputs [Hash] The input arguments
|
|
127
127
|
# @raise [GraphQL::ExecutionError] To add an error to the response
|
|
128
128
|
# @raise [GraphQL::UnauthorizedError] To signal an authorization failure
|
|
129
129
|
# @return [Boolean, early_return_data] If `false`, execution will stop (and `early_return_data` will be returned instead, if present.)
|
|
130
|
-
def authorized?(**
|
|
131
|
-
|
|
130
|
+
def authorized?(**inputs)
|
|
131
|
+
self.class.arguments.each_value do |argument|
|
|
132
|
+
arg_keyword = argument.keyword
|
|
133
|
+
if inputs.key?(arg_keyword) && !(value = inputs[arg_keyword]).nil? && (value != argument.default_value)
|
|
134
|
+
loads_type = @arguments_loads_as_type[arg_keyword]
|
|
135
|
+
# If this argument resulted in an object being loaded,
|
|
136
|
+
# then authorize this loaded object with its own policy.
|
|
137
|
+
#
|
|
138
|
+
# But if this argument was "just" a plain argument, like
|
|
139
|
+
# a boolean, then authorize it based on the mutation.
|
|
140
|
+
authorization_value = if loads_type
|
|
141
|
+
value
|
|
142
|
+
else
|
|
143
|
+
self
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
arg_auth, err = argument.authorized?(authorization_value, context)
|
|
147
|
+
if !arg_auth
|
|
148
|
+
return arg_auth, err
|
|
149
|
+
else
|
|
150
|
+
true
|
|
151
|
+
end
|
|
152
|
+
else
|
|
153
|
+
true
|
|
154
|
+
end
|
|
155
|
+
end
|
|
132
156
|
end
|
|
133
157
|
|
|
134
158
|
private
|
|
@@ -254,12 +278,11 @@ module GraphQL
|
|
|
254
278
|
# Add an argument to this field's signature, but
|
|
255
279
|
# also add some preparation hook methods which will be used for this argument
|
|
256
280
|
# @see {GraphQL::Schema::Argument#initialize} for the signature
|
|
257
|
-
def argument(
|
|
258
|
-
|
|
259
|
-
#
|
|
281
|
+
def argument(*args, **kwargs, &block)
|
|
282
|
+
loads = kwargs[:loads]
|
|
283
|
+
# Use `from_resolver: true` to short-circuit the InputObject's own `loads:` implementation
|
|
260
284
|
# so that we can support `#load_{x}` methods below.
|
|
261
|
-
|
|
262
|
-
arg_defn = super(*args, **kwargs)
|
|
285
|
+
arg_defn = super(*args, from_resolver: true, **kwargs)
|
|
263
286
|
own_arguments_loads_as_type[arg_defn.keyword] = loads if loads
|
|
264
287
|
|
|
265
288
|
if loads && arg_defn.type.list?
|
|
@@ -27,7 +27,7 @@ module GraphQL
|
|
|
27
27
|
if new_class
|
|
28
28
|
@field_class = new_class
|
|
29
29
|
else
|
|
30
|
-
@field_class ||
|
|
30
|
+
@field_class || find_inherited_value(:field_class, GraphQL::Schema::Field)
|
|
31
31
|
end
|
|
32
32
|
end
|
|
33
33
|
|
|
@@ -37,8 +37,9 @@ module GraphQL
|
|
|
37
37
|
def object_class(new_class = nil)
|
|
38
38
|
if new_class
|
|
39
39
|
@object_class = new_class
|
|
40
|
+
else
|
|
41
|
+
@object_class || find_inherited_value(:object_class, GraphQL::Schema::Object)
|
|
40
42
|
end
|
|
41
|
-
@object_class || (superclass.respond_to?(:object_class) ? superclass.object_class : GraphQL::Schema::Object)
|
|
42
43
|
end
|
|
43
44
|
|
|
44
45
|
private
|
|
@@ -17,7 +17,7 @@ module GraphQL
|
|
|
17
17
|
|
|
18
18
|
def assert_required_args(ast_node, defn)
|
|
19
19
|
present_argument_names = ast_node.arguments.map(&:name)
|
|
20
|
-
required_argument_names =
|
|
20
|
+
required_argument_names = context.warden.arguments(defn)
|
|
21
21
|
.select { |a| a.type.kind.non_null? }
|
|
22
22
|
.map(&:name)
|
|
23
23
|
|
data/lib/graphql/version.rb
CHANGED
|
@@ -31,6 +31,8 @@ describe GraphQL::Analysis do
|
|
|
31
31
|
end
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
let(:schema) { Class.new(Dummy::Schema) }
|
|
35
|
+
|
|
34
36
|
describe ".analyze_query" do
|
|
35
37
|
let(:node_counter) {
|
|
36
38
|
->(memo, visit_type, irep_node) {
|
|
@@ -43,7 +45,7 @@ describe GraphQL::Analysis do
|
|
|
43
45
|
let(:analyzers) { [type_collector, node_counter] }
|
|
44
46
|
let(:reduce_result) { GraphQL::Analysis.analyze_query(query, analyzers) }
|
|
45
47
|
let(:variables) { {} }
|
|
46
|
-
let(:query) { GraphQL::Query.new(
|
|
48
|
+
let(:query) { GraphQL::Query.new(schema, query_string, variables: variables) }
|
|
47
49
|
let(:query_string) {%|
|
|
48
50
|
{
|
|
49
51
|
cheese(id: 1) {
|
|
@@ -58,7 +60,7 @@ describe GraphQL::Analysis do
|
|
|
58
60
|
let(:analyzers) { [type_collector, conditional_analyzer] }
|
|
59
61
|
|
|
60
62
|
describe "when analyze? returns false" do
|
|
61
|
-
let(:query) { GraphQL::Query.new(
|
|
63
|
+
let(:query) { GraphQL::Query.new(schema, query_string, variables: variables, context: { analyze: false }) }
|
|
62
64
|
|
|
63
65
|
it "does not run the analyzer" do
|
|
64
66
|
# Only type_collector ran
|
|
@@ -67,7 +69,7 @@ describe GraphQL::Analysis do
|
|
|
67
69
|
end
|
|
68
70
|
|
|
69
71
|
describe "when analyze? returns true" do
|
|
70
|
-
let(:query) { GraphQL::Query.new(
|
|
72
|
+
let(:query) { GraphQL::Query.new(schema, query_string, variables: variables, context: { analyze: true }) }
|
|
71
73
|
|
|
72
74
|
it "it runs the analyzer" do
|
|
73
75
|
# Both analyzers ran
|
|
@@ -93,7 +95,7 @@ describe GraphQL::Analysis do
|
|
|
93
95
|
it "emits traces" do
|
|
94
96
|
traces = TestTracing.with_trace do
|
|
95
97
|
ctx = { tracers: [TestTracing] }
|
|
96
|
-
|
|
98
|
+
schema.execute(query_string, context: ctx)
|
|
97
99
|
end
|
|
98
100
|
|
|
99
101
|
# The query_trace is on the list _first_ because it finished first
|
|
@@ -119,14 +121,7 @@ describe GraphQL::Analysis do
|
|
|
119
121
|
let(:variable_accessor) { ->(memo, visit_type, irep_node) { query.variables["cheeseId"] } }
|
|
120
122
|
|
|
121
123
|
before do
|
|
122
|
-
|
|
123
|
-
Dummy::Schema.query_analyzers.clear
|
|
124
|
-
Dummy::Schema.query_analyzers << variable_accessor
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
after do
|
|
128
|
-
Dummy::Schema.query_analyzers.clear
|
|
129
|
-
Dummy::Schema.query_analyzers.push(*@previous_query_analyzers)
|
|
124
|
+
schema.query_analyzer(variable_accessor)
|
|
130
125
|
end
|
|
131
126
|
|
|
132
127
|
it "returns an error" do
|
|
@@ -213,7 +208,7 @@ describe GraphQL::Analysis do
|
|
|
213
208
|
let(:flavor_catcher) { FlavorCatcher.new }
|
|
214
209
|
let(:analyzers) { [id_catcher, flavor_catcher] }
|
|
215
210
|
let(:reduce_result) { GraphQL::Analysis.analyze_query(query, analyzers) }
|
|
216
|
-
let(:query) { GraphQL::Query.new(
|
|
211
|
+
let(:query) { GraphQL::Query.new(schema, query_string) }
|
|
217
212
|
let(:query_string) {%|
|
|
218
213
|
{
|
|
219
214
|
cheese(id: 1) {
|
|
@@ -222,7 +217,12 @@ describe GraphQL::Analysis do
|
|
|
222
217
|
}
|
|
223
218
|
}
|
|
224
219
|
|}
|
|
225
|
-
let(:schema)
|
|
220
|
+
let(:schema) do
|
|
221
|
+
schema = Class.new(Dummy::Schema)
|
|
222
|
+
schema.query_analyzer(id_catcher)
|
|
223
|
+
schema.query_analyzer(flavor_catcher)
|
|
224
|
+
schema
|
|
225
|
+
end
|
|
226
226
|
let(:result) { schema.execute(query_string) }
|
|
227
227
|
let(:query_string) {%|
|
|
228
228
|
{
|
|
@@ -233,17 +233,6 @@ describe GraphQL::Analysis do
|
|
|
233
233
|
}
|
|
234
234
|
|}
|
|
235
235
|
|
|
236
|
-
before do
|
|
237
|
-
@previous_query_analyzers = Dummy::Schema.query_analyzers.dup
|
|
238
|
-
Dummy::Schema.query_analyzers.clear
|
|
239
|
-
Dummy::Schema.query_analyzers << id_catcher << flavor_catcher
|
|
240
|
-
end
|
|
241
|
-
|
|
242
|
-
after do
|
|
243
|
-
Dummy::Schema.query_analyzers.clear
|
|
244
|
-
Dummy::Schema.query_analyzers.push(*@previous_query_analyzers)
|
|
245
|
-
end
|
|
246
|
-
|
|
247
236
|
it "groups all errors together" do
|
|
248
237
|
data = result["data"]
|
|
249
238
|
errors = result["errors"]
|