graphql 2.0.22 → 2.0.24

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2564f5f0788db163950385832a4255c88b47b72ddb45175ec30f0f42c6dc0b04
4
- data.tar.gz: c1760c1a43453ece3baed09bde3e30f6012bd4357ec597781e4616a7c67a2bc4
3
+ metadata.gz: 7c97d63232efb5f7ecdaef0f8102a73ceaa4a4b0a3b06c7ab1f613735efafa59
4
+ data.tar.gz: aff3df56a3db15d97f457e92fffab33f29440fed5ca84b0515794ad051e5631e
5
5
  SHA512:
6
- metadata.gz: 4e1d1747ceb4450228b9b7cb9b123f61585fe8eea3d6442627b56818f4a146e2b507e5a0b8665e25334a64dca79eb8a089c2aa0ff3e8d710fb6adec080623da0
7
- data.tar.gz: f1ec3b93d97f4546184496aed5bc03d5ba1a5af1655aaeeb40ac20461e7c722431a116ca8e1a019d8b7e7eda59e7748f862985ea1dd131b3005ceb9ca3c9fa7c
6
+ metadata.gz: 3cf33d0ed4df848c57e459f9ee023b0a6b2814d14ef09d7c304120a595cd62e65f25b05b3f16448c89cfb9479d06e550611c42fa76b3fb92a677c788f31f713e
7
+ data.tar.gz: 28b8d5e3fb2d6cc0bc3ebbdaf6f6d53dc16b0225bcafcc0fe72d4956afb9ff0fdb1ca929093ad466951dc28a30d893e643c8fb68bff69df374e41e1c43e2980b
@@ -55,9 +55,5 @@ module GraphQL
55
55
  @parent_frame = parent_frame
56
56
  end
57
57
  end
58
-
59
- class DefaultBacktraceTrace < GraphQL::Tracing::Trace
60
- include GraphQL::Backtrace::Trace
61
- end
62
58
  end
63
59
  end
@@ -39,7 +39,7 @@ module GraphQL
39
39
  result_for(key)
40
40
  else
41
41
  @pending_keys << key
42
- sync
42
+ sync([key])
43
43
  result_for(key)
44
44
  end
45
45
  end
@@ -50,7 +50,7 @@ module GraphQL
50
50
  if keys.any? { |k| !@results.key?(k) }
51
51
  pending_keys = keys.select { |k| !@results.key?(k) }
52
52
  @pending_keys.concat(pending_keys)
53
- sync
53
+ sync(pending_keys)
54
54
  end
55
55
 
56
56
  keys.map { |k| result_for(k) }
@@ -67,8 +67,7 @@ module GraphQL
67
67
  # Wait for a batch, if there's anything to batch.
68
68
  # Then run the batch and update the cache.
69
69
  # @return [void]
70
- def sync
71
- pending_keys = @pending_keys.dup
70
+ def sync(pending_keys)
72
71
  @dataloader.yield
73
72
  iterations = 0
74
73
  while pending_keys.any? { |k| !@results.key?(k) }
@@ -247,15 +247,15 @@ module GraphQL
247
247
  st = get_current_runtime_state
248
248
  st.current_object = query.root_value
249
249
  st.current_result = @response
250
- object_proxy = authorized_new(root_type, query.root_value, context)
251
- object_proxy = schema.sync_lazy(object_proxy)
250
+ runtime_object = root_type.wrap(query.root_value, context)
251
+ runtime_object = schema.sync_lazy(runtime_object)
252
252
 
253
- if object_proxy.nil?
253
+ if runtime_object.nil?
254
254
  # Root .authorized? returned false.
255
255
  @response = nil
256
256
  else
257
- call_method_on_directives(:resolve, object_proxy, root_operation.directives) do # execute query level directives
258
- gathered_selections = gather_selections(object_proxy, root_type, root_operation.selections)
257
+ call_method_on_directives(:resolve, runtime_object, root_operation.directives) do # execute query level directives
258
+ gathered_selections = gather_selections(runtime_object, root_type, root_operation.selections)
259
259
  # This is kind of a hack -- `gathered_selections` is an Array if any of the selections
260
260
  # require isolation during execution (because of runtime directives). In that case,
261
261
  # make a new, isolated result hash for writing the result into. (That isolated response
@@ -280,9 +280,9 @@ module GraphQL
280
280
  if (directives = selections[:graphql_directives])
281
281
  selections.delete(:graphql_directives)
282
282
  end
283
- call_method_on_directives(:resolve, object_proxy, directives) do
283
+ call_method_on_directives(:resolve, runtime_object, directives) do
284
284
  evaluate_selections(
285
- object_proxy,
285
+ runtime_object,
286
286
  root_type,
287
287
  root_op_type == "mutation",
288
288
  selections,
@@ -343,12 +343,8 @@ module GraphQL
343
343
  if node.type
344
344
  type_defn = schema.get_type(node.type.name, context)
345
345
 
346
- # Faster than .map{}.include?()
347
- query.warden.possible_types(type_defn).each do |t|
348
- if t == owner_type
349
- gather_selections(owner_object, owner_type, node.selections, selections_to_run, next_selections)
350
- break
351
- end
346
+ if query.warden.possible_types(type_defn).include?(owner_type)
347
+ gather_selections(owner_object, owner_type, node.selections, selections_to_run, next_selections)
352
348
  end
353
349
  else
354
350
  # it's an untyped fragment, definitely continue
@@ -357,12 +353,8 @@ module GraphQL
357
353
  when GraphQL::Language::Nodes::FragmentSpread
358
354
  fragment_def = query.fragments[node.name]
359
355
  type_defn = query.get_type(fragment_def.type.name)
360
- possible_types = query.warden.possible_types(type_defn)
361
- possible_types.each do |t|
362
- if t == owner_type
363
- gather_selections(owner_object, owner_type, fragment_def.selections, selections_to_run, next_selections)
364
- break
365
- end
356
+ if query.warden.possible_types(type_defn).include?(owner_type)
357
+ gather_selections(owner_object, owner_type, fragment_def.selections, selections_to_run, next_selections)
366
358
  end
367
359
  else
368
360
  raise "Invariant: unexpected selection class: #{node.class}"
@@ -446,10 +438,8 @@ module GraphQL
446
438
  st.current_result = selections_result
447
439
  st.current_result_name = result_name
448
440
 
449
- object = owner_object
450
-
451
441
  if is_introspection
452
- object = authorized_new(field_defn.owner, object, context)
442
+ owner_object = field_defn.owner.wrap(owner_object, context)
453
443
  end
454
444
 
455
445
  total_args_count = field_defn.arguments(context).size
@@ -457,14 +447,14 @@ module GraphQL
457
447
  resolved_arguments = GraphQL::Execution::Interpreter::Arguments::EMPTY
458
448
  if field_defn.extras.size == 0
459
449
  evaluate_selection_with_resolved_keyword_args(
460
- NO_ARGS, resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, object, is_eager_field, result_name, selections_result, parent_object, return_type, return_type_non_null
450
+ NO_ARGS, resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, owner_object, is_eager_field, result_name, selections_result, parent_object, return_type, return_type_non_null
461
451
  )
462
452
  else
463
- evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, object, is_eager_field, result_name, selections_result, parent_object, return_type, return_type_non_null)
453
+ evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, owner_object, is_eager_field, result_name, selections_result, parent_object, return_type, return_type_non_null)
464
454
  end
465
455
  else
466
- @query.arguments_cache.dataload_for(ast_node, field_defn, object) do |resolved_arguments|
467
- evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, object, is_eager_field, result_name, selections_result, parent_object, return_type, return_type_non_null)
456
+ @query.arguments_cache.dataload_for(ast_node, field_defn, owner_object) do |resolved_arguments|
457
+ evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, owner_object, is_eager_field, result_name, selections_result, parent_object, return_type, return_type_non_null)
468
458
  end
469
459
  end
470
460
  end
@@ -782,7 +772,7 @@ module GraphQL
782
772
  end
783
773
  when "OBJECT"
784
774
  object_proxy = begin
785
- authorized_new(current_type, value, context)
775
+ current_type.wrap(value, context)
786
776
  rescue GraphQL::ExecutionError => err
787
777
  err
788
778
  end
@@ -1055,10 +1045,6 @@ module GraphQL
1055
1045
  end
1056
1046
  end
1057
1047
 
1058
- def authorized_new(type, value, context)
1059
- type.authorized_new(value, context)
1060
- end
1061
-
1062
1048
  def lazy?(object)
1063
1049
  obj_class = object.class
1064
1050
  is_lazy = @lazy_cache[obj_class]
@@ -11,7 +11,7 @@ module GraphQL
11
11
  # Apply wrapping manually since this field isn't wrapped by instrumentation
12
12
  schema = @context.query.schema
13
13
  schema_type = schema.introspection_system.types["__Schema"]
14
- schema_type.authorized_new(schema, @context)
14
+ schema_type.wrap(schema, @context)
15
15
  end
16
16
 
17
17
  def __type(name:)
@@ -36,7 +36,10 @@ module GraphQL
36
36
  context: schema_context,
37
37
  )
38
38
  else
39
- GraphQL::Schema::Warden.new(schema: @schema, context: schema_context)
39
+ @schema.warden_class.new(
40
+ schema: @schema,
41
+ context: schema_context,
42
+ )
40
43
  end
41
44
 
42
45
  schema_context.warden = @warden
@@ -131,7 +131,7 @@ module GraphQL
131
131
  "$#{variable_identifier.name}".dup
132
132
  end
133
133
 
134
- def print_schema_definition(schema)
134
+ def print_schema_definition(schema, extension: false)
135
135
  has_conventional_names = (schema.query.nil? || schema.query == 'Query') &&
136
136
  (schema.mutation.nil? || schema.mutation == 'Mutation') &&
137
137
  (schema.subscription.nil? || schema.subscription == 'Subscription')
@@ -140,7 +140,7 @@ module GraphQL
140
140
  return
141
141
  end
142
142
 
143
- out = "schema".dup
143
+ out = extension ? "extend schema".dup : "schema".dup
144
144
  if schema.directives.any?
145
145
  schema.directives.each do |dir|
146
146
  out << "\n "
@@ -164,14 +164,14 @@ module GraphQL
164
164
  out
165
165
  end
166
166
 
167
- def print_scalar_type_definition(scalar_type)
168
- out = print_description(scalar_type)
167
+ def print_scalar_type_definition(scalar_type, extension: false)
168
+ out = extension ? "extend ".dup : print_description(scalar_type)
169
169
  out << "scalar #{scalar_type.name}"
170
170
  out << print_directives(scalar_type.directives)
171
171
  end
172
172
 
173
- def print_object_type_definition(object_type)
174
- out = print_description(object_type)
173
+ def print_object_type_definition(object_type, extension: false)
174
+ out = extension ? "extend ".dup : print_description(object_type)
175
175
  out << "type #{object_type.name}"
176
176
  out << print_implements(object_type) unless object_type.interfaces.empty?
177
177
  out << print_directives(object_type.directives)
@@ -210,23 +210,23 @@ module GraphQL
210
210
  out << print_directives(field.directives)
211
211
  end
212
212
 
213
- def print_interface_type_definition(interface_type)
214
- out = print_description(interface_type)
213
+ def print_interface_type_definition(interface_type, extension: false)
214
+ out = extension ? "extend ".dup : print_description(interface_type)
215
215
  out << "interface #{interface_type.name}"
216
216
  out << print_implements(interface_type) if interface_type.interfaces.any?
217
217
  out << print_directives(interface_type.directives)
218
218
  out << print_field_definitions(interface_type.fields)
219
219
  end
220
220
 
221
- def print_union_type_definition(union_type)
222
- out = print_description(union_type)
221
+ def print_union_type_definition(union_type, extension: false)
222
+ out = extension ? "extend ".dup : print_description(union_type)
223
223
  out << "union #{union_type.name}"
224
224
  out << print_directives(union_type.directives)
225
225
  out << " = " + union_type.types.map(&:name).join(" | ")
226
226
  end
227
227
 
228
- def print_enum_type_definition(enum_type)
229
- out = print_description(enum_type)
228
+ def print_enum_type_definition(enum_type, extension: false)
229
+ out = extension ? "extend ".dup : print_description(enum_type)
230
230
  out << "enum #{enum_type.name}#{print_directives(enum_type.directives)} {\n"
231
231
  enum_type.values.each.with_index do |value, i|
232
232
  out << print_description(value, indent: ' ', first_in_block: i == 0)
@@ -241,8 +241,8 @@ module GraphQL
241
241
  out << "\n"
242
242
  end
243
243
 
244
- def print_input_object_type_definition(input_object_type)
245
- out = print_description(input_object_type)
244
+ def print_input_object_type_definition(input_object_type, extension: false)
245
+ out = extension ? "extend ".dup : print_description(input_object_type)
246
246
  out << "input #{input_object_type.name}"
247
247
  out << print_directives(input_object_type.directives)
248
248
  if !input_object_type.fields.empty?
@@ -347,24 +347,38 @@ module GraphQL
347
347
  print_variable_identifier(node)
348
348
  when Nodes::SchemaDefinition
349
349
  print_schema_definition(node)
350
+ when Nodes::SchemaExtension
351
+ print_schema_definition(node, extension: true)
350
352
  when Nodes::ScalarTypeDefinition
351
353
  print_scalar_type_definition(node)
354
+ when Nodes::ScalarTypeExtension
355
+ print_scalar_type_definition(node, extension: true)
352
356
  when Nodes::ObjectTypeDefinition
353
357
  print_object_type_definition(node)
358
+ when Nodes::ObjectTypeExtension
359
+ print_object_type_definition(node, extension: true)
354
360
  when Nodes::InputValueDefinition
355
361
  print_input_value_definition(node)
356
362
  when Nodes::FieldDefinition
357
363
  print_field_definition(node)
358
364
  when Nodes::InterfaceTypeDefinition
359
365
  print_interface_type_definition(node)
366
+ when Nodes::InterfaceTypeExtension
367
+ print_interface_type_definition(node, extension: true)
360
368
  when Nodes::UnionTypeDefinition
361
369
  print_union_type_definition(node)
370
+ when Nodes::UnionTypeExtension
371
+ print_union_type_definition(node, extension: true)
362
372
  when Nodes::EnumTypeDefinition
363
373
  print_enum_type_definition(node)
374
+ when Nodes::EnumTypeExtension
375
+ print_enum_type_definition(node, extension: true)
364
376
  when Nodes::EnumValueDefinition
365
377
  print_enum_value_definition(node)
366
378
  when Nodes::InputObjectTypeDefinition
367
379
  print_input_object_type_definition(node)
380
+ when Nodes::InputObjectTypeExtension
381
+ print_input_object_type_definition(node, extension: true)
368
382
  when Nodes::DirectiveDefinition
369
383
  print_directive_definition(node)
370
384
  when FalseClass, Float, Integer, NilClass, String, TrueClass, Symbol
@@ -3,14 +3,6 @@ module GraphQL
3
3
  class Query
4
4
  # This object can be `ctx` in places where there is no query
5
5
  class NullContext
6
- class NullWarden < GraphQL::Schema::Warden
7
- def visible_field?(field, ctx); true; end
8
- def visible_argument?(arg, ctx); true; end
9
- def visible_type?(type, ctx); true; end
10
- def visible_enum_value?(ev, ctx); true; end
11
- def visible_type_membership?(tm, ctx); true; end
12
- end
13
-
14
6
  class NullQuery
15
7
  def after_lazy(value)
16
8
  yield(value)
@@ -20,21 +12,18 @@ module GraphQL
20
12
  class NullSchema < GraphQL::Schema
21
13
  end
22
14
 
15
+ extend Forwardable
16
+
23
17
  attr_reader :schema, :query, :warden, :dataloader
18
+ def_delegators GraphQL::EmptyObjects::EMPTY_HASH, :[], :fetch, :dig, :key?
24
19
 
25
20
  def initialize
26
21
  @query = NullQuery.new
27
22
  @dataloader = GraphQL::Dataloader::NullDataloader.new
28
23
  @schema = NullSchema
29
- @warden = NullWarden.new(
30
- GraphQL::Filter.new(silence_deprecation_warning: true),
31
- context: self,
32
- schema: @schema,
33
- )
24
+ @warden = Schema::Warden::NullWarden.new(context: self, schema: @schema)
34
25
  end
35
26
 
36
- def [](key); end
37
-
38
27
  def interpreter?
39
28
  true
40
29
  end
@@ -42,13 +31,11 @@ module GraphQL
42
31
  class << self
43
32
  extend Forwardable
44
33
 
45
- def [](key); end
46
-
47
34
  def instance
48
35
  @instance ||= self.new
49
36
  end
50
37
 
51
- def_delegators :instance, :query, :warden, :schema, :interpreter?, :dataloader
38
+ def_delegators :instance, :query, :warden, :schema, :interpreter?, :dataloader, :[], :fetch, :dig, :key?
52
39
  end
53
40
  end
54
41
  end
@@ -68,7 +68,8 @@ module GraphQL
68
68
  elsif @operation_name_error
69
69
  @validation_errors << @operation_name_error
70
70
  else
71
- validation_result = @schema.static_validator.validate(@query, validate: @query.validate, timeout: @schema.validate_timeout, max_errors: @schema.validate_max_errors)
71
+ validator = @query.static_validator || @schema.static_validator
72
+ validation_result = validator.validate(@query, validate: @query.validate, timeout: @schema.validate_timeout, max_errors: @schema.validate_max_errors)
72
73
  @validation_errors.concat(validation_result[:errors])
73
74
 
74
75
  if @validation_errors.empty?
data/lib/graphql/query.rb CHANGED
@@ -45,6 +45,20 @@ module GraphQL
45
45
  end
46
46
  end
47
47
 
48
+ # @return [GraphQL::StaticValidation::Validator] if present, the query will validate with these rules.
49
+ attr_reader :static_validator
50
+
51
+ # @param new_validate [GraphQL::StaticValidation::Validator] if present, the query will validate with these rules. This can't be reasssigned after validation.
52
+ def static_validator=(new_validator)
53
+ if defined?(@validation_pipeline) && @validation_pipeline && @validation_pipeline.has_validated?
54
+ raise ArgumentError, "Can't reassign Query#static_validator= after validation has run, remove this assignment."
55
+ elsif !new_validator.is_a?(GraphQL::StaticValidation::Validator)
56
+ raise ArgumentError, "Expected a `GraphQL::StaticValidation::Validator` instance."
57
+ else
58
+ @static_validator = new_validator
59
+ end
60
+ end
61
+
48
62
  attr_writer :query_string
49
63
 
50
64
  # @return [GraphQL::Language::Nodes::Document]
@@ -83,7 +97,7 @@ module GraphQL
83
97
  # @param max_complexity [Numeric] the maximum field complexity for this query (falls back to schema-level value)
84
98
  # @param except [<#call(schema_member, context)>] If provided, objects will be hidden from the schema when `.call(schema_member, context)` returns truthy
85
99
  # @param only [<#call(schema_member, context)>] If provided, objects will be hidden from the schema when `.call(schema_member, context)` returns false
86
- def initialize(schema, query_string = nil, query: nil, document: nil, context: nil, variables: nil, validate: true, subscription_topic: nil, operation_name: nil, root_value: nil, max_depth: schema.max_depth, max_complexity: schema.max_complexity, except: nil, only: nil, warden: nil)
100
+ def initialize(schema, query_string = nil, query: nil, document: nil, context: nil, variables: nil, validate: true, static_validator: nil, subscription_topic: nil, operation_name: nil, root_value: nil, max_depth: schema.max_depth, max_complexity: schema.max_complexity, except: nil, only: nil, warden: nil)
87
101
  # Even if `variables: nil` is passed, use an empty hash for simpler logic
88
102
  variables ||= {}
89
103
  @schema = schema
@@ -97,12 +111,13 @@ module GraphQL
97
111
  @fragments = nil
98
112
  @operations = nil
99
113
  @validate = validate
114
+ self.static_validator = static_validator if static_validator
100
115
  context_tracers = (context ? context.fetch(:tracers, []) : [])
101
116
  @tracers = schema.tracers + context_tracers
102
117
 
103
118
  # Support `ctx[:backtrace] = true` for wrapping backtraces
104
119
  if context && context[:backtrace] && !@tracers.include?(GraphQL::Backtrace::Tracer)
105
- if schema.trace_class <= GraphQL::Tracing::LegacyTrace
120
+ if schema.trace_class <= GraphQL::Tracing::CallLegacyTracers
106
121
  context_tracers += [GraphQL::Backtrace::Tracer]
107
122
  @tracers << GraphQL::Backtrace::Tracer
108
123
  elsif !(current_trace.class <= GraphQL::Backtrace::Trace)
@@ -110,8 +125,8 @@ module GraphQL
110
125
  end
111
126
  end
112
127
 
113
- if context_tracers.any? && !(schema.trace_class <= GraphQL::Tracing::LegacyTrace)
114
- raise ArgumentError, "context[:tracers] are not supported without `trace_class(GraphQL::Tracing::LegacyTrace)` in the schema configuration, please add it."
128
+ if context_tracers.any? && !(schema.trace_class <= GraphQL::Tracing::CallLegacyTracers)
129
+ raise ArgumentError, "context[:tracers] are not supported without `trace_with(GraphQL::Tracing::CallLegacyTracers)` in the schema configuration, please add it."
115
130
  end
116
131
 
117
132
 
@@ -168,7 +183,7 @@ module GraphQL
168
183
 
169
184
  # @return [GraphQL::Tracing::Trace]
170
185
  def current_trace
171
- @current_trace ||= multiplex ? multiplex.current_trace : schema.new_trace(multiplex: multiplex, query: self)
186
+ @current_trace ||= context[:trace] || (multiplex ? multiplex.current_trace : schema.new_trace(multiplex: multiplex, query: self))
172
187
  end
173
188
 
174
189
  def subscription_update?
@@ -385,7 +400,7 @@ module GraphQL
385
400
 
386
401
  def prepare_ast
387
402
  @prepared_ast = true
388
- @warden ||= GraphQL::Schema::Warden.new(@filter, schema: @schema, context: @context)
403
+ @warden ||= @schema.warden_class.new(@filter, schema: @schema, context: @context)
389
404
  parse_error = nil
390
405
  @document ||= begin
391
406
  if query_string
@@ -40,14 +40,21 @@ module GraphQL
40
40
  end
41
41
 
42
42
  def add_directives_from(owner)
43
- dirs = owner.directives.map(&:class)
44
- @directives.merge(dirs)
45
- add_type_and_traverse(dirs)
43
+ if (dir_instances = owner.directives).any?
44
+ dirs = dir_instances.map(&:class)
45
+ @directives.merge(dirs)
46
+ add_type_and_traverse(dirs)
47
+ end
46
48
  end
47
49
 
48
50
  def add_type_and_traverse(new_types)
49
51
  late_types = []
50
- new_types.each { |t| add_type(t, owner: nil, late_types: late_types, path: [t.graphql_name]) }
52
+ path = []
53
+ new_types.each do |t|
54
+ path.push(t.graphql_name)
55
+ add_type(t, owner: nil, late_types: late_types, path: path)
56
+ path.pop
57
+ end
51
58
  missed_late_types = 0
52
59
  while (late_type_vals = late_types.shift)
53
60
  type_owner, lt = late_type_vals
@@ -158,7 +165,9 @@ module GraphQL
158
165
  type.all_argument_definitions.each do |arg|
159
166
  arg_type = arg.type.unwrap
160
167
  references_to(arg_type, from: arg)
161
- add_type(arg_type, owner: arg, late_types: late_types, path: path + [arg.graphql_name])
168
+ path.push(arg.graphql_name)
169
+ add_type(arg_type, owner: arg, late_types: late_types, path: path)
170
+ path.pop
162
171
  if arg.default_value?
163
172
  @arguments_with_default_values << arg
164
173
  end
@@ -179,18 +188,21 @@ module GraphQL
179
188
  name = field.graphql_name
180
189
  field_type = field.type.unwrap
181
190
  references_to(field_type, from: field)
182
- field_path = path + [name]
183
- add_type(field_type, owner: field, late_types: late_types, path: field_path)
191
+ path.push(name)
192
+ add_type(field_type, owner: field, late_types: late_types, path: path)
184
193
  add_directives_from(field)
185
194
  field.all_argument_definitions.each do |arg|
186
195
  add_directives_from(arg)
187
196
  arg_type = arg.type.unwrap
188
197
  references_to(arg_type, from: arg)
189
- add_type(arg_type, owner: arg, late_types: late_types, path: field_path + [arg.graphql_name])
198
+ path.push(arg.graphql_name)
199
+ add_type(arg_type, owner: arg, late_types: late_types, path: path)
200
+ path.pop
190
201
  if arg.default_value?
191
202
  @arguments_with_default_values << arg
192
203
  end
193
204
  end
205
+ path.pop
194
206
  end
195
207
  end
196
208
  if type.kind.input_object?
@@ -198,7 +210,9 @@ module GraphQL
198
210
  add_directives_from(arg)
199
211
  arg_type = arg.type.unwrap
200
212
  references_to(arg_type, from: arg)
201
- add_type(arg_type, owner: arg, late_types: late_types, path: path + [arg.graphql_name])
213
+ path.push(arg.graphql_name)
214
+ add_type(arg_type, owner: arg, late_types: late_types, path: path)
215
+ path.pop
202
216
  if arg.default_value?
203
217
  @arguments_with_default_values << arg
204
218
  end
@@ -206,14 +220,18 @@ module GraphQL
206
220
  end
207
221
  if type.kind.union?
208
222
  @possible_types[type.graphql_name] = type.all_possible_types
223
+ path.push("possible_types")
209
224
  type.all_possible_types.each do |t|
210
- add_type(t, owner: type, late_types: late_types, path: path + ["possible_types"])
225
+ add_type(t, owner: type, late_types: late_types, path: path)
211
226
  end
227
+ path.pop
212
228
  end
213
229
  if type.kind.interface?
230
+ path.push("orphan_types")
214
231
  type.orphan_types.each do |t|
215
- add_type(t, owner: type, late_types: late_types, path: path + ["orphan_types"])
232
+ add_type(t, owner: type, late_types: late_types, path: path)
216
233
  end
234
+ path.pop
217
235
  end
218
236
  if type.kind.object?
219
237
  possible_types_for_this_name = @possible_types[type.graphql_name] ||= []
@@ -221,6 +239,7 @@ module GraphQL
221
239
  end
222
240
 
223
241
  if type.kind.object? || type.kind.interface?
242
+ path.push("implements")
224
243
  type.interface_type_memberships.each do |interface_type_membership|
225
244
  case interface_type_membership
226
245
  when Schema::TypeMembership
@@ -235,8 +254,9 @@ module GraphQL
235
254
  else
236
255
  raise ArgumentError, "Invariant: unexpected type membership for #{type.graphql_name}: #{interface_type_membership.class} (#{interface_type_membership.inspect})"
237
256
  end
238
- add_type(interface_type, owner: type, late_types: late_types, path: path + ["implements"])
257
+ add_type(interface_type, owner: type, late_types: late_types, path: path)
239
258
  end
259
+ path.pop
240
260
  end
241
261
  end
242
262
  end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ class Schema
4
+ class AlwaysVisible
5
+ def self.use(schema, **opts)
6
+ schema.warden_class = GraphQL::Schema::Warden::NullWarden
7
+ end
8
+ end
9
+ end
10
+ end
@@ -339,7 +339,7 @@ module GraphQL
339
339
  self.validates(validates)
340
340
  end
341
341
 
342
- if definition_block
342
+ if block_given?
343
343
  if definition_block.arity == 1
344
344
  yield self
345
345
  else
@@ -810,6 +810,17 @@ ERR
810
810
  end
811
811
  end
812
812
 
813
+ class ExtendedState
814
+ def initialize(args, object)
815
+ @arguments = args
816
+ @object = object
817
+ @memos = nil
818
+ @added_extras = nil
819
+ end
820
+
821
+ attr_accessor :arguments, :object, :memos, :added_extras
822
+ end
823
+
813
824
  # Wrap execution with hooks.
814
825
  # Written iteratively to avoid big stack traces.
815
826
  # @return [Object] Whatever the
@@ -820,18 +831,18 @@ ERR
820
831
  # This is a hack to get the _last_ value for extended obj and args,
821
832
  # in case one of the extensions doesn't `yield`.
822
833
  # (There's another implementation that uses multiple-return, but I'm wary of the perf cost of the extra arrays)
823
- extended = { args: args, obj: obj, memos: nil, added_extras: nil }
834
+ extended = ExtendedState.new(args, obj)
824
835
  value = run_extensions_before_resolve(obj, args, ctx, extended) do |obj, args|
825
- if (added_extras = extended[:added_extras])
836
+ if (added_extras = extended.added_extras)
826
837
  args = args.dup
827
838
  added_extras.each { |e| args.delete(e) }
828
839
  end
829
840
  yield(obj, args)
830
841
  end
831
842
 
832
- extended_obj = extended[:obj]
833
- extended_args = extended[:args]
834
- memos = extended[:memos] || EMPTY_HASH
843
+ extended_obj = extended.object
844
+ extended_args = extended.arguments # rubocop:disable Development/ContextIsPassedCop
845
+ memos = extended.memos || EMPTY_HASH
835
846
 
836
847
  ctx.query.after_lazy(value) do |resolved_value|
837
848
  idx = 0
@@ -851,17 +862,17 @@ ERR
851
862
  if extension
852
863
  extension.resolve(object: obj, arguments: args, context: ctx) do |extended_obj, extended_args, memo|
853
864
  if memo
854
- memos = extended[:memos] ||= {}
865
+ memos = extended.memos ||= {}
855
866
  memos[idx] = memo
856
867
  end
857
868
 
858
869
  if (extras = extension.added_extras)
859
- ae = extended[:added_extras] ||= []
870
+ ae = extended.added_extras ||= []
860
871
  ae.concat(extras)
861
872
  end
862
873
 
863
- extended[:obj] = extended_obj
864
- extended[:args] = extended_args
874
+ extended.object = extended_obj
875
+ extended.arguments = extended_args
865
876
  run_extensions_before_resolve(extended_obj, extended_args, ctx, extended, idx: idx + 1) { |o, a| yield(o, a) }
866
877
  end
867
878
  else
@@ -155,7 +155,7 @@ module GraphQL
155
155
  if obj.is_a?(GraphQL::Schema::Object)
156
156
  obj = obj.object
157
157
  end
158
- wrapped_object = @object_class.authorized_new(obj, query_ctx)
158
+ wrapped_object = @object_class.wrap(obj, query_ctx)
159
159
  @inner_resolve.call(wrapped_object, args, ctx)
160
160
  end
161
161
  end
@@ -109,7 +109,14 @@ module GraphQL
109
109
  to_type_name(something.name)
110
110
  end
111
111
  when String
112
- something.gsub(/\]\[\!/, "").split("::").last
112
+ if something.include?("]") ||
113
+ something.include?("[") ||
114
+ something.include?("!") ||
115
+ something.include?("::")
116
+ something.gsub(/\]\[\!/, "").split("::").last
117
+ else
118
+ something
119
+ end
113
120
  when GraphQL::Schema::NonNull, GraphQL::Schema::List
114
121
  to_type_name(something.unwrap)
115
122
  else
@@ -122,7 +129,8 @@ module GraphQL
122
129
  return string unless string.include?("_")
123
130
  camelized = string.split('_').each(&:capitalize!).join
124
131
  camelized[0] = camelized[0].downcase
125
- if (match_data = string.match(/\A(_+)/))
132
+ if string.start_with?("_")
133
+ match_data = string.match(/\A(_+)/)
126
134
  camelized = "#{match_data[0]}#{camelized}"
127
135
  end
128
136
  camelized
@@ -30,6 +30,11 @@ module GraphQL
30
30
  # @see authorized_new to make instances
31
31
  protected :new
32
32
 
33
+ # This is called by the runtime to return an object to call methods on.
34
+ def wrap(object, context)
35
+ authorized_new(object, context)
36
+ end
37
+
33
38
  # Make a new instance of this type _if_ the auth check passes,
34
39
  # otherwise, raise an error.
35
40
  #
@@ -90,7 +90,7 @@ module GraphQL
90
90
  # The default implementation returns the `max_seconds:` value from installing this plugin.
91
91
  #
92
92
  # @param query [GraphQL::Query] The query that's about to run
93
- # @return [Integer, false] The number of seconds after which to interrupt query execution and call {#handle_error}, or `false` to bypass the timeout.
93
+ # @return [Numeric, false] The number of seconds after which to interrupt query execution and call {#handle_error}, or `false` to bypass the timeout.
94
94
  def max_seconds(query)
95
95
  @max_seconds
96
96
  end
@@ -38,8 +38,9 @@ module GraphQL
38
38
  # @api private
39
39
  class Warden
40
40
  def self.from_context(context)
41
- context.warden # this might be a hash which won't respond to this
42
- rescue
41
+ context.warden || PassThruWarden
42
+ rescue NoMethodError
43
+ # this might be a hash which won't respond to #warden
43
44
  PassThruWarden
44
45
  end
45
46
 
@@ -87,6 +88,32 @@ module GraphQL
87
88
  end
88
89
  end
89
90
 
91
+ class NullWarden
92
+ def initialize(_filter = nil, context:, schema:)
93
+ @schema = schema
94
+ end
95
+
96
+ def visible_field?(field_defn, _ctx = nil, owner = nil); true; end
97
+ def visible_argument?(arg_defn, _ctx = nil); true; end
98
+ def visible_type?(type_defn, _ctx = nil); true; end
99
+ def visible_enum_value?(enum_value, _ctx = nil); true; end
100
+ def visible_type_membership?(type_membership, _ctx = nil); true; end
101
+ def interface_type_memberships(obj_type, _ctx = nil); obj_type.interface_type_memberships; end
102
+ def get_type(type_name); @schema.get_type(type_name); end # rubocop:disable Development/ContextIsPassedCop
103
+ def arguments(argument_owner, ctx = nil); argument_owner.all_argument_definitions; end
104
+ def enum_values(enum_defn); enum_defn.enum_values; end # rubocop:disable Development/ContextIsPassedCop
105
+ def get_argument(parent_type, argument_name); parent_type.get_argument(argument_name); end # rubocop:disable Development/ContextIsPassedCop
106
+ def types; @schema.types; end # rubocop:disable Development/ContextIsPassedCop
107
+ def root_type_for_operation(op_name); @schema.root_type_for_operation(op_name); end
108
+ def directives; @schema.directives.values; end
109
+ def fields(type_defn); type_defn.all_field_definitions; end # rubocop:disable Development/ContextIsPassedCop
110
+ def get_field(parent_type, field_name); @schema.get_field(parent_type, field_name); end
111
+ def reachable_type?(type_name); true; end
112
+ def reachable_types; @schema.types.values; end # rubocop:disable Development/ContextIsPassedCop
113
+ def possible_types(type_defn); @schema.possible_types(type_defn); end
114
+ def interfaces(obj_type); obj_type.interfaces; end
115
+ end
116
+
90
117
  # @param filter [<#call(member)>] Objects are hidden when `.call(member, ctx)` returns true
91
118
  # @param context [GraphQL::Query::Context]
92
119
  # @param schema [GraphQL::Schema]
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require "graphql/schema/addition"
3
+ require "graphql/schema/always_visible"
3
4
  require "graphql/schema/base_64_encoder"
4
5
  require "graphql/schema/find_inherited_value"
5
6
  require "graphql/schema/finder"
@@ -157,14 +158,17 @@ module GraphQL
157
158
  def trace_class_for(mode)
158
159
  @trace_modes ||= {}
159
160
  @trace_modes[mode] ||= begin
160
- base_class = if superclass.respond_to?(:trace_class_for)
161
- superclass.trace_class_for(mode)
162
- elsif mode == :default_backtrace
163
- GraphQL::Backtrace::DefaultBacktraceTrace
161
+ if mode == :default_backtrace
162
+ schema_base_class = trace_class_for(:default)
163
+ Class.new(schema_base_class) do
164
+ include(GraphQL::Backtrace::Trace)
165
+ end
166
+ elsif superclass.respond_to?(:trace_class_for)
167
+ superclass_base_class = superclass.trace_class_for(mode)
168
+ Class.new(superclass_base_class)
164
169
  else
165
- GraphQL::Tracing::Trace
170
+ Class.new(GraphQL::Tracing::Trace)
166
171
  end
167
- Class.new(base_class)
168
172
  end
169
173
  end
170
174
 
@@ -420,6 +424,18 @@ module GraphQL
420
424
  @root_types
421
425
  end
422
426
 
427
+ def warden_class
428
+ if defined?(@warden_class)
429
+ @warden_class
430
+ elsif superclass.respond_to?(:warden_class)
431
+ superclass.warden_class
432
+ else
433
+ GraphQL::Schema::Warden
434
+ end
435
+ end
436
+
437
+ attr_writer :warden_class
438
+
423
439
  # @param type [Module] The type definition whose possible types you want to see
424
440
  # @return [Hash<String, Module>] All possible types, if no `type` is given.
425
441
  # @return [Array<Module>] Possible types for `type`, if it's given.
@@ -961,10 +977,8 @@ module GraphQL
961
977
  end
962
978
 
963
979
  def tracer(new_tracer)
964
- if defined?(@trace_modes) && !(trace_class_for(:default) < GraphQL::Tracing::LegacyTrace)
965
- raise ArgumentError, "Can't add tracer after configuring a `trace_class`, use GraphQL::Tracing::LegacyTrace to merge legacy tracers into a trace class instead."
966
- else
967
- trace_mode(:default, Class.new(GraphQL::Tracing::LegacyTrace))
980
+ if !(trace_class_for(:default) < GraphQL::Tracing::CallLegacyTracers)
981
+ trace_with(GraphQL::Tracing::CallLegacyTracers)
968
982
  end
969
983
 
970
984
  own_tracers << new_tracer
@@ -1036,6 +1050,7 @@ module GraphQL
1036
1050
  {
1037
1051
  backtrace: ctx[:backtrace],
1038
1052
  tracers: ctx[:tracers],
1053
+ trace: ctx[:trace],
1039
1054
  dataloader: ctx[:dataloader],
1040
1055
  }
1041
1056
  else
@@ -4,7 +4,7 @@ module GraphQL
4
4
  # This trace class calls legacy-style tracer with payload hashes.
5
5
  # New-style `trace_with` modules significantly reduce the overhead of tracing,
6
6
  # but that advantage is lost when legacy-style tracers are also used (since the payload hashes are still constructed).
7
- class LegacyTrace < Trace
7
+ module CallLegacyTracers
8
8
  def lex(query_string:)
9
9
  (@multiplex || @query).trace("lex", { query_string: query_string }) { super }
10
10
  end
@@ -61,5 +61,9 @@ module GraphQL
61
61
  query.trace("resolve_type_lazy", { context: query.context, type: type, object: object, path: query.context[:current_path] }) { super }
62
62
  end
63
63
  end
64
+
65
+ class LegacyTrace < Trace
66
+ include CallLegacyTracers
67
+ end
64
68
  end
65
69
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "2.0.22"
3
+ VERSION = "2.0.24"
4
4
  end
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: 2.0.22
4
+ version: 2.0.24
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-05-17 00:00:00.000000000 Z
11
+ date: 2023-06-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: benchmark-ips
@@ -395,6 +395,7 @@ files:
395
395
  - lib/graphql/runtime_type_error.rb
396
396
  - lib/graphql/schema.rb
397
397
  - lib/graphql/schema/addition.rb
398
+ - lib/graphql/schema/always_visible.rb
398
399
  - lib/graphql/schema/argument.rb
399
400
  - lib/graphql/schema/base_64_bp.rb
400
401
  - lib/graphql/schema/base_64_encoder.rb
@@ -622,7 +623,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
622
623
  - !ruby/object:Gem::Version
623
624
  version: '0'
624
625
  requirements: []
625
- rubygems_version: 3.4.13
626
+ rubygems_version: 3.2.33
626
627
  signing_key:
627
628
  specification_version: 4
628
629
  summary: A GraphQL language and runtime for Ruby