graphql 2.0.22 → 2.0.24

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.

Potentially problematic release.


This version of graphql might be problematic. Click here for more details.

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