graphql 2.3.2 → 2.3.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 573ce6f5423ca2d9eb0ca3dab40f01869501f834c3b48d5cac7f7c06fbf36da9
4
- data.tar.gz: c3b1f0393d2838a2478a36a43cec88560832c220a3896f2ee4c715d013d1758c
3
+ metadata.gz: d1511256e7812b5c2de2a01ffa44f8a77f2e8959837344eaf1c8780d0b1bf700
4
+ data.tar.gz: 87a0734b541d8f2cbbd3fb293a63663cbc57c61e6ab39242449596c6ca759442
5
5
  SHA512:
6
- metadata.gz: 14d6c96c20c8fdb56ecddf0279e24e83c862d4133c72b3cebc44dca9e40e1c684b4f4a4c45fca81451d48d1bb97a4e6c3ae13499a40e12a76926e679a12a13f2
7
- data.tar.gz: 44157aaa761da8c9f82afa9e31533ee3c87cdf4257256ec84f70f0e30dff8dc1830486c2ff02b4464a67e8815518466451ae598eabc12249cf2edaad6a9371f1
6
+ metadata.gz: fff5ef36d8e8dff310cac664178ebf0e902cd067a893fedd164902625751fe457a070f1daf2a2251d0dd2ec57fb16daccc81b54267048bbb71c027caf7905100
7
+ data.tar.gz: 5fc4e6c4a44398e9f77d99c5224d22128a9c80e64a17a156500337b4d658270da9aa7af71f8d06cc065939cc42b41de3e07d66cb7622704ad179424c312dd7a0
@@ -8,6 +8,7 @@ module GraphQL
8
8
  # - `complexities_on_type` holds complexity scores for each type
9
9
  def initialize(query)
10
10
  super
11
+ @skip_introspection_fields = !query.schema.max_complexity_count_introspection_fields
11
12
  @complexities_on_type_by_query = {}
12
13
  end
13
14
 
@@ -51,6 +52,7 @@ module GraphQL
51
52
  # we'll visit them when we hit the spreads instead
52
53
  return if visitor.visiting_fragment_definition?
53
54
  return if visitor.skipping?
55
+ return if @skip_introspection_fields && visitor.field_definition.introspection?
54
56
  parent_type = visitor.parent_type_definition
55
57
  field_key = node.alias || node.name
56
58
 
@@ -68,6 +70,7 @@ module GraphQL
68
70
  # we'll visit them when we hit the spreads instead
69
71
  return if visitor.visiting_fragment_definition?
70
72
  return if visitor.skipping?
73
+ return if @skip_introspection_fields && visitor.field_definition.introspection?
71
74
  scopes_stack = @complexities_on_type_by_query[visitor.query]
72
75
  scopes_stack.pop
73
76
  end
@@ -5,8 +5,10 @@ module GraphQL
5
5
  class Interpreter
6
6
  class Runtime
7
7
  module GraphQLResult
8
- def initialize(result_name, parent_result, is_non_null_in_parent)
8
+ def initialize(result_name, result_type, application_value, parent_result, is_non_null_in_parent)
9
9
  @graphql_parent = parent_result
10
+ @graphql_application_value = application_value
11
+ @graphql_result_type = result_type
10
12
  if parent_result && parent_result.graphql_dead
11
13
  @graphql_dead = true
12
14
  end
@@ -26,14 +28,14 @@ module GraphQL
26
28
  end
27
29
 
28
30
  attr_accessor :graphql_dead
29
- attr_reader :graphql_parent, :graphql_result_name, :graphql_is_non_null_in_parent
31
+ attr_reader :graphql_parent, :graphql_result_name, :graphql_is_non_null_in_parent, :graphql_application_value, :graphql_result_type
30
32
 
31
33
  # @return [Hash] Plain-Ruby result data (`@graphql_metadata` contains Result wrapper objects)
32
34
  attr_accessor :graphql_result_data
33
35
  end
34
36
 
35
37
  class GraphQLResultHash
36
- def initialize(_result_name, _parent_result, _is_non_null_in_parent)
38
+ def initialize(_result_name, _result_type, _application_value, _parent_result, _is_non_null_in_parent)
37
39
  super
38
40
  @graphql_result_data = {}
39
41
  end
@@ -121,7 +123,7 @@ module GraphQL
121
123
  class GraphQLResultArray
122
124
  include GraphQLResult
123
125
 
124
- def initialize(_result_name, _parent_result, _is_non_null_in_parent)
126
+ def initialize(_result_name, _result_type, _application_value, _parent_result, _is_non_null_in_parent)
125
127
  super
126
128
  @graphql_result_data = []
127
129
  end
@@ -11,7 +11,6 @@ module GraphQL
11
11
  class Runtime
12
12
  class CurrentState
13
13
  def initialize
14
- @current_object = nil
15
14
  @current_field = nil
16
15
  @current_arguments = nil
17
16
  @current_result_name = nil
@@ -19,8 +18,12 @@ module GraphQL
19
18
  @was_authorized_by_scope_items = nil
20
19
  end
21
20
 
21
+ def current_object
22
+ @current_result.graphql_application_value
23
+ end
24
+
22
25
  attr_accessor :current_result, :current_result_name,
23
- :current_arguments, :current_field, :current_object, :was_authorized_by_scope_items
26
+ :current_arguments, :current_field, :was_authorized_by_scope_items
24
27
  end
25
28
 
26
29
  # @return [GraphQL::Query]
@@ -39,7 +42,7 @@ module GraphQL
39
42
  @lazies_at_depth = lazies_at_depth
40
43
  @schema = query.schema
41
44
  @context = query.context
42
- @response = GraphQLResultHash.new(nil, nil, false)
45
+ @response = nil
43
46
  # Identify runtime directives by checking which of this schema's directives have overridden `def self.resolve`
44
47
  @runtime_directive_names = []
45
48
  noop_resolve_owner = GraphQL::Schema::Directive.singleton_class
@@ -79,12 +82,11 @@ module GraphQL
79
82
  root_operation = query.selected_operation
80
83
  root_op_type = root_operation.operation_type || "query"
81
84
  root_type = schema.root_type_for_operation(root_op_type)
82
-
83
- st = get_current_runtime_state
84
- st.current_object = query.root_value
85
- st.current_result = @response
86
85
  runtime_object = root_type.wrap(query.root_value, context)
87
86
  runtime_object = schema.sync_lazy(runtime_object)
87
+ @response = GraphQLResultHash.new(nil, root_type, runtime_object, nil, false)
88
+ st = get_current_runtime_state
89
+ st.current_result = @response
88
90
 
89
91
  if runtime_object.nil?
90
92
  # Root .authorized? returned false.
@@ -101,7 +103,7 @@ module GraphQL
101
103
  # directly evaluated and the results can be written right into the main response hash.
102
104
  tap_or_each(gathered_selections) do |selections, is_selection_array|
103
105
  if is_selection_array
104
- selection_response = GraphQLResultHash.new(nil, nil, false)
106
+ selection_response = GraphQLResultHash.new(nil, root_type, runtime_object, nil, false)
105
107
  final_response = @response
106
108
  else
107
109
  selection_response = @response
@@ -109,26 +111,14 @@ module GraphQL
109
111
  end
110
112
 
111
113
  @dataloader.append_job {
112
- st = get_current_runtime_state
113
- st.current_object = query.root_value
114
- st.current_result_name = nil
115
- st.current_result = selection_response
116
- # This is a less-frequent case; use a fast check since it's often not there.
117
- if (directives = selections[:graphql_directives])
118
- selections.delete(:graphql_directives)
119
- end
120
- call_method_on_directives(:resolve, runtime_object, directives) do
121
- evaluate_selections(
122
- runtime_object,
123
- root_type,
124
- root_op_type == "mutation",
125
- selections,
126
- selection_response,
127
- final_response,
128
- nil,
129
- st,
130
- )
131
- end
114
+ evaluate_selections(
115
+ root_op_type == "mutation",
116
+ selections,
117
+ selection_response,
118
+ final_response,
119
+ nil,
120
+ nil,
121
+ )
132
122
  }
133
123
  end
134
124
  end
@@ -205,36 +195,44 @@ module GraphQL
205
195
  NO_ARGS = GraphQL::EmptyObjects::EMPTY_HASH
206
196
 
207
197
  # @return [void]
208
- def evaluate_selections(owner_object, owner_type, is_eager_selection, gathered_selections, selections_result, target_result, parent_object, runtime_state) # rubocop:disable Metrics/ParameterLists
209
- finished_jobs = 0
210
- enqueued_jobs = gathered_selections.size
211
- gathered_selections.each do |result_name, field_ast_nodes_or_ast_node|
212
- @dataloader.append_job {
213
- runtime_state = get_current_runtime_state
214
- evaluate_selection(
215
- result_name, field_ast_nodes_or_ast_node, owner_object, owner_type, is_eager_selection, selections_result, parent_object, runtime_state
216
- )
217
- finished_jobs += 1
218
- if target_result && finished_jobs == enqueued_jobs
219
- selections_result.merge_into(target_result)
198
+ def evaluate_selections(is_eager_selection, gathered_selections, selections_result, target_result, parent_object, runtime_state) # rubocop:disable Metrics/ParameterLists
199
+ runtime_state ||= get_current_runtime_state
200
+ runtime_state.current_result_name = nil
201
+ runtime_state.current_result = selections_result
202
+ # This is a less-frequent case; use a fast check since it's often not there.
203
+ if (directives = gathered_selections[:graphql_directives])
204
+ gathered_selections.delete(:graphql_directives)
205
+ end
206
+
207
+ call_method_on_directives(:resolve, selections_result.graphql_application_value, directives) do
208
+ finished_jobs = 0
209
+ enqueued_jobs = gathered_selections.size
210
+ gathered_selections.each do |result_name, field_ast_nodes_or_ast_node|
211
+ @dataloader.append_job {
212
+ evaluate_selection(
213
+ result_name, field_ast_nodes_or_ast_node, is_eager_selection, selections_result, parent_object
214
+ )
215
+ finished_jobs += 1
216
+ if target_result && finished_jobs == enqueued_jobs
217
+ selections_result.merge_into(target_result)
218
+ end
219
+ }
220
+ # Field resolution may pause the fiber,
221
+ # so it wouldn't get to the `Resolve` call that happens below.
222
+ # So instead trigger a run from this outer context.
223
+ if is_eager_selection
224
+ @dataloader.clear_cache
225
+ @dataloader.run
226
+ @dataloader.clear_cache
220
227
  end
221
- }
222
- # Field resolution may pause the fiber,
223
- # so it wouldn't get to the `Resolve` call that happens below.
224
- # So instead trigger a run from this outer context.
225
- if is_eager_selection
226
- @dataloader.clear_cache
227
- @dataloader.run
228
- @dataloader.clear_cache
229
228
  end
229
+ selections_result
230
230
  end
231
-
232
- selections_result
233
231
  end
234
232
 
235
233
  # @return [void]
236
- def evaluate_selection(result_name, field_ast_nodes_or_ast_node, owner_object, owner_type, is_eager_field, selections_result, parent_object, runtime_state) # rubocop:disable Metrics/ParameterLists
237
- return if dead_result?(selections_result)
234
+ def evaluate_selection(result_name, field_ast_nodes_or_ast_node, is_eager_field, selections_result, parent_object) # rubocop:disable Metrics/ParameterLists
235
+ return if selections_result.graphql_dead
238
236
  # As a performance optimization, the hash key will be a `Node` if
239
237
  # there's only one selection of the field. But if there are multiple
240
238
  # selections of the field, it will be an Array of nodes
@@ -246,13 +244,16 @@ module GraphQL
246
244
  ast_node = field_ast_nodes_or_ast_node
247
245
  end
248
246
  field_name = ast_node.name
247
+ owner_type = selections_result.graphql_result_type
249
248
  field_defn = query.warden.get_field(owner_type, field_name)
250
249
 
251
250
  # Set this before calling `run_with_directives`, so that the directive can have the latest path
251
+ runtime_state = get_current_runtime_state
252
252
  runtime_state.current_field = field_defn
253
253
  runtime_state.current_result = selections_result
254
254
  runtime_state.current_result_name = result_name
255
255
 
256
+ owner_object = selections_result.graphql_application_value
256
257
  if field_defn.dynamic_introspection
257
258
  owner_object = field_defn.owner.wrap(owner_object, context)
258
259
  end
@@ -262,24 +263,24 @@ module GraphQL
262
263
  resolved_arguments = GraphQL::Execution::Interpreter::Arguments::EMPTY
263
264
  if field_defn.extras.size == 0
264
265
  evaluate_selection_with_resolved_keyword_args(
265
- 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?, runtime_state
266
+ NO_ARGS, resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_object, is_eager_field, result_name, selections_result, parent_object, return_type, return_type.non_null?, runtime_state
266
267
  )
267
268
  else
268
- 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, runtime_state)
269
+ evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_object, is_eager_field, result_name, selections_result, parent_object, return_type, runtime_state)
269
270
  end
270
271
  else
271
272
  @query.arguments_cache.dataload_for(ast_node, field_defn, owner_object) do |resolved_arguments|
272
273
  runtime_state = get_current_runtime_state # This might be in a different fiber
273
- 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, runtime_state)
274
+ evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_object, is_eager_field, result_name, selections_result, parent_object, return_type, runtime_state)
274
275
  end
275
276
  end
276
277
  end
277
278
 
278
- def evaluate_selection_with_args(arguments, field_defn, ast_node, field_ast_nodes, owner_type, object, is_eager_field, result_name, selection_result, parent_object, return_type, runtime_state) # rubocop:disable Metrics/ParameterLists
279
+ def evaluate_selection_with_args(arguments, field_defn, ast_node, field_ast_nodes, object, is_eager_field, result_name, selection_result, parent_object, return_type, runtime_state) # rubocop:disable Metrics/ParameterLists
279
280
  after_lazy(arguments, field: field_defn, ast_node: ast_node, owner_object: object, arguments: arguments, result_name: result_name, result: selection_result, runtime_state: runtime_state) do |resolved_arguments, runtime_state|
280
281
  return_type_non_null = return_type.non_null?
281
282
  if resolved_arguments.is_a?(GraphQL::ExecutionError) || resolved_arguments.is_a?(GraphQL::UnauthorizedError)
282
- continue_value(resolved_arguments, owner_type, field_defn, return_type_non_null, ast_node, result_name, selection_result)
283
+ continue_value(resolved_arguments, field_defn, return_type_non_null, ast_node, result_name, selection_result)
283
284
  next
284
285
  end
285
286
 
@@ -328,13 +329,12 @@ module GraphQL
328
329
  resolved_arguments.keyword_arguments
329
330
  end
330
331
 
331
- evaluate_selection_with_resolved_keyword_args(kwarg_arguments, resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, object, is_eager_field, result_name, selection_result, parent_object, return_type, return_type_non_null, runtime_state)
332
+ evaluate_selection_with_resolved_keyword_args(kwarg_arguments, resolved_arguments, field_defn, ast_node, field_ast_nodes, object, is_eager_field, result_name, selection_result, parent_object, return_type, return_type_non_null, runtime_state)
332
333
  end
333
334
  end
334
335
 
335
- def evaluate_selection_with_resolved_keyword_args(kwarg_arguments, resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, object, is_eager_field, result_name, selection_result, parent_object, return_type, return_type_non_null, runtime_state) # rubocop:disable Metrics/ParameterLists
336
+ def evaluate_selection_with_resolved_keyword_args(kwarg_arguments, resolved_arguments, field_defn, ast_node, field_ast_nodes, object, is_eager_field, result_name, selection_result, parent_object, return_type, return_type_non_null, runtime_state) # rubocop:disable Metrics/ParameterLists
336
337
  runtime_state.current_field = field_defn
337
- runtime_state.current_object = object
338
338
  runtime_state.current_arguments = resolved_arguments
339
339
  runtime_state.current_result_name = result_name
340
340
  runtime_state.current_result = selection_result
@@ -356,7 +356,6 @@ module GraphQL
356
356
  # This might be executed in a different context; reset this info
357
357
  runtime_state = get_current_runtime_state
358
358
  runtime_state.current_field = field_defn
359
- runtime_state.current_object = object
360
359
  runtime_state.current_arguments = resolved_arguments
361
360
  runtime_state.current_result_name = result_name
362
361
  runtime_state.current_result = selection_result
@@ -376,7 +375,8 @@ module GraphQL
376
375
  end
377
376
  end
378
377
  after_lazy(app_result, field: field_defn, ast_node: ast_node, owner_object: object, arguments: resolved_arguments, result_name: result_name, result: selection_result, runtime_state: runtime_state) do |inner_result, runtime_state|
379
- continue_value = continue_value(inner_result, owner_type, field_defn, return_type_non_null, ast_node, result_name, selection_result)
378
+ owner_type = selection_result.graphql_result_type
379
+ continue_value = continue_value(inner_result, field_defn, return_type_non_null, ast_node, result_name, selection_result)
380
380
  if HALT != continue_value
381
381
  was_scoped = runtime_state.was_authorized_by_scope_items
382
382
  runtime_state.was_authorized_by_scope_items = nil
@@ -384,25 +384,16 @@ module GraphQL
384
384
  end
385
385
  end
386
386
  end
387
-
388
387
  # If this field is a root mutation field, immediately resolve
389
388
  # all of its child fields before moving on to the next root mutation field.
390
389
  # (Subselections of this mutation will still be resolved level-by-level.)
391
390
  if is_eager_field
392
391
  Interpreter::Resolve.resolve_all([field_result], @dataloader)
393
- else
394
- # Return this from `after_lazy` because it might be another lazy that needs to be resolved
395
- field_result
396
392
  end
397
393
  end
398
394
 
399
-
400
- def dead_result?(selection_result)
401
- selection_result.graphql_dead # || ((parent = selection_result.graphql_parent) && parent.graphql_dead)
402
- end
403
-
404
395
  def set_result(selection_result, result_name, value, is_child_result, is_non_null)
405
- if !dead_result?(selection_result)
396
+ if !selection_result.graphql_dead
406
397
  if value.nil? && is_non_null
407
398
  # This is an invalid nil that should be propagated
408
399
  # One caller of this method passes a block,
@@ -456,11 +447,13 @@ module GraphQL
456
447
  end
457
448
 
458
449
  HALT = Object.new
459
- def continue_value(value, parent_type, field, is_non_null, ast_node, result_name, selection_result) # rubocop:disable Metrics/ParameterLists
450
+ def continue_value(value, field, is_non_null, ast_node, result_name, selection_result) # rubocop:disable Metrics/ParameterLists
460
451
  case value
461
452
  when nil
462
453
  if is_non_null
463
454
  set_result(selection_result, result_name, nil, false, is_non_null) do
455
+ # When this comes from a list item, use the parent object:
456
+ parent_type = selection_result.is_a?(GraphQLResultArray) ? selection_result.graphql_parent.graphql_result_type : selection_result.graphql_result_type
464
457
  # This block is called if `result_name` is not dead. (Maybe a previous invalid nil caused it be marked dead.)
465
458
  err = parent_type::InvalidNullError.new(parent_type, field, value)
466
459
  schema.type_error(err, context)
@@ -474,7 +467,7 @@ module GraphQL
474
467
  # to avoid the overhead of checking three different classes
475
468
  # every time.
476
469
  if value.is_a?(GraphQL::ExecutionError)
477
- if selection_result.nil? || !dead_result?(selection_result)
470
+ if selection_result.nil? || !selection_result.graphql_dead
478
471
  value.path ||= current_path
479
472
  value.ast_node ||= ast_node
480
473
  context.errors << value
@@ -492,7 +485,7 @@ module GraphQL
492
485
  rescue GraphQL::ExecutionError => err
493
486
  err
494
487
  end
495
- continue_value(next_value, parent_type, field, is_non_null, ast_node, result_name, selection_result)
488
+ continue_value(next_value, field, is_non_null, ast_node, result_name, selection_result)
496
489
  elsif value.is_a?(GraphQL::UnauthorizedError)
497
490
  # this hook might raise & crash, or it might return
498
491
  # a replacement value
@@ -501,7 +494,7 @@ module GraphQL
501
494
  rescue GraphQL::ExecutionError => err
502
495
  err
503
496
  end
504
- continue_value(next_value, parent_type, field, is_non_null, ast_node, result_name, selection_result)
497
+ continue_value(next_value, field, is_non_null, ast_node, result_name, selection_result)
505
498
  elsif GraphQL::Execution::SKIP == value
506
499
  # It's possible a lazy was already written here
507
500
  case selection_result
@@ -524,7 +517,7 @@ module GraphQL
524
517
  # It's an array full of execution errors; add them all.
525
518
  if value.any? && value.all?(GraphQL::ExecutionError)
526
519
  list_type_at_all = (field && (field.type.list?))
527
- if selection_result.nil? || !dead_result?(selection_result)
520
+ if selection_result.nil? || !selection_result.graphql_dead
528
521
  value.each_with_index do |error, index|
529
522
  error.ast_node ||= ast_node
530
523
  error.path ||= current_path + (list_type_at_all ? [index] : [])
@@ -604,9 +597,9 @@ module GraphQL
604
597
  err
605
598
  end
606
599
  after_lazy(object_proxy, ast_node: ast_node, field: field, owner_object: owner_object, arguments: arguments, trace: false, result_name: result_name, result: selection_result, runtime_state: runtime_state) do |inner_object, runtime_state|
607
- continue_value = continue_value(inner_object, owner_type, field, is_non_null, ast_node, result_name, selection_result)
600
+ continue_value = continue_value(inner_object, field, is_non_null, ast_node, result_name, selection_result)
608
601
  if HALT != continue_value
609
- response_hash = GraphQLResultHash.new(result_name, selection_result, is_non_null)
602
+ response_hash = GraphQLResultHash.new(result_name, current_type, continue_value, selection_result, is_non_null)
610
603
  set_result(selection_result, result_name, response_hash, true, is_non_null)
611
604
 
612
605
  gathered_selections = gather_selections(continue_value, current_type, next_selections)
@@ -620,34 +613,21 @@ module GraphQL
620
613
  # (Technically, it's possible that one of those entries _doesn't_ require isolation.)
621
614
  tap_or_each(gathered_selections) do |selections, is_selection_array|
622
615
  if is_selection_array
623
- this_result = GraphQLResultHash.new(result_name, selection_result, is_non_null)
616
+ this_result = GraphQLResultHash.new(result_name, current_type, continue_value, selection_result, is_non_null)
624
617
  final_result = response_hash
625
618
  else
626
619
  this_result = response_hash
627
620
  final_result = nil
628
621
  end
629
- # reset this mutable state
630
- # Unset `result_name` here because it's already included in the new response hash
631
- runtime_state.current_object = continue_value
632
- runtime_state.current_result_name = nil
633
- runtime_state.current_result = this_result
634
- # This is a less-frequent case; use a fast check since it's often not there.
635
- if (directives = selections[:graphql_directives])
636
- selections.delete(:graphql_directives)
637
- end
638
- call_method_on_directives(:resolve, continue_value, directives) do
639
- evaluate_selections(
640
- continue_value,
641
- current_type,
642
- false,
643
- selections,
644
- this_result,
645
- final_result,
646
- owner_object.object,
647
- runtime_state,
648
- )
649
- this_result
650
- end
622
+
623
+ evaluate_selections(
624
+ false,
625
+ selections,
626
+ this_result,
627
+ final_result,
628
+ owner_object.object,
629
+ runtime_state,
630
+ )
651
631
  end
652
632
  end
653
633
  end
@@ -656,7 +636,7 @@ module GraphQL
656
636
  # This is true for objects, unions, and interfaces
657
637
  use_dataloader_job = !inner_type.unwrap.kind.input?
658
638
  inner_type_non_null = inner_type.non_null?
659
- response_list = GraphQLResultArray.new(result_name, selection_result, is_non_null)
639
+ response_list = GraphQLResultArray.new(result_name, current_type, response_list, selection_result, is_non_null)
660
640
  set_result(selection_result, result_name, response_list, true, is_non_null)
661
641
  idx = nil
662
642
  list_value = begin
@@ -694,7 +674,7 @@ module GraphQL
694
674
  end
695
675
  # Detect whether this error came while calling `.each` (before `idx` is set) or while running list *items* (after `idx` is set)
696
676
  error_is_non_null = idx.nil? ? is_non_null : inner_type.non_null?
697
- continue_value(list_value, owner_type, field, error_is_non_null, ast_node, result_name, selection_result)
677
+ continue_value(list_value, field, error_is_non_null, ast_node, result_name, selection_result)
698
678
  else
699
679
  raise "Invariant: Unhandled type kind #{current_type.kind} (#{current_type})"
700
680
  end
@@ -706,7 +686,7 @@ module GraphQL
706
686
  call_method_on_directives(:resolve_each, owner_object, ast_node.directives) do
707
687
  # This will update `response_list` with the lazy
708
688
  after_lazy(inner_value, ast_node: ast_node, field: field, owner_object: owner_object, arguments: arguments, result_name: this_idx, result: response_list, runtime_state: runtime_state) do |inner_inner_value, runtime_state|
709
- continue_value = continue_value(inner_inner_value, owner_type, field, inner_type_non_null, ast_node, this_idx, response_list)
689
+ continue_value = continue_value(inner_inner_value, field, inner_type_non_null, ast_node, this_idx, response_list)
710
690
  if HALT != continue_value
711
691
  continue_field(continue_value, owner_type, field, inner_type, ast_node, next_selections, false, owner_object, arguments, this_idx, response_list, was_scoped, runtime_state)
712
692
  end
@@ -728,7 +708,6 @@ module GraphQL
728
708
  raw_dir_args = arguments(nil, dir_defn, dir_node)
729
709
  dir_args = continue_value(
730
710
  raw_dir_args, # value
731
- dir_defn, # parent_type
732
711
  nil, # field
733
712
  false, # is_non_null
734
713
  dir_node, # ast_node
@@ -794,7 +773,6 @@ module GraphQL
794
773
  # In that case, this will initialize a new state
795
774
  # to avoid conflicting with the parent fiber.
796
775
  runtime_state = get_current_runtime_state
797
- runtime_state.current_object = owner_object
798
776
  runtime_state.current_field = field
799
777
  runtime_state.current_arguments = arguments
800
778
  runtime_state.current_result_name = result_name
@@ -25,21 +25,15 @@ module GraphQL
25
25
  attr_reader :filename
26
26
 
27
27
  def line
28
- @line ||= (@source_string && @pos) ? @source_string[0..@pos].count("\n") + 1 : nil
28
+ @line ||= @source.line_at(@pos)
29
29
  end
30
30
 
31
31
  def col
32
- @col ||= if @source_string && @pos
33
- if @pos == 0
34
- 1
35
- else
36
- @source_string[0..@pos].split("\n").last.length
37
- end
38
- end
32
+ @col ||= @source.column_at(@pos)
39
33
  end
40
34
 
41
35
  def definition_line
42
- @definition_line ||= (@source_string && @definition_pos) ? @source_string[0..@definition_pos].count("\n") + 1 : nil
36
+ @definition_line ||= (@source && @definition_pos) ? @source.line_at(@definition_pos) : nil
43
37
  end
44
38
 
45
39
  # Value equality
@@ -267,7 +261,7 @@ module GraphQL
267
261
  "col: nil",
268
262
  "pos: nil",
269
263
  "filename: nil",
270
- "source_string: nil",
264
+ "source: nil",
271
265
  ]
272
266
 
273
267
  def generate_initialize
@@ -306,7 +300,7 @@ module GraphQL
306
300
  @col = col
307
301
  @pos = pos
308
302
  @filename = filename
309
- @source_string = source_string
303
+ @source = source
310
304
  #{assignments.join("\n")}
311
305
  end
312
306
 
@@ -385,7 +379,7 @@ module GraphQL
385
379
  # @!attribute selections
386
380
  # @return [Array<Nodes::Field>] Selections on this object (or empty array if this is a scalar field)
387
381
 
388
- def initialize(name: nil, arguments: NONE, directives: NONE, selections: NONE, field_alias: nil, line: nil, col: nil, pos: nil, filename: nil, source_string: nil)
382
+ def initialize(name: nil, arguments: NONE, directives: NONE, selections: NONE, field_alias: nil, line: nil, col: nil, pos: nil, filename: nil, source: nil)
389
383
  @name = name
390
384
  @arguments = arguments || NONE
391
385
  @directives = directives || NONE
@@ -396,7 +390,7 @@ module GraphQL
396
390
  @col = col
397
391
  @pos = pos
398
392
  @filename = filename
399
- @source_string = source_string
393
+ @source = source
400
394
  end
401
395
 
402
396
  def self.from_a(filename, line, col, field_alias, name, arguments, directives, selections) # rubocop:disable Metrics/ParameterLists
@@ -421,14 +415,14 @@ module GraphQL
421
415
 
422
416
  # @!attribute type
423
417
  # @return [String] the type condition for this fragment (name of type which it may apply to)
424
- def initialize(name: nil, type: nil, directives: NONE, selections: NONE, filename: nil, pos: nil, source_string: nil, line: nil, col: nil)
418
+ def initialize(name: nil, type: nil, directives: NONE, selections: NONE, filename: nil, pos: nil, source: nil, line: nil, col: nil)
425
419
  @name = name
426
420
  @type = type
427
421
  @directives = directives
428
422
  @selections = selections
429
423
  @filename = filename
430
424
  @pos = pos
431
- @source_string = source_string
425
+ @source = source
432
426
  @line = line
433
427
  @col = col
434
428
  end
@@ -36,6 +36,7 @@ module GraphQL
36
36
  @filename = filename
37
37
  @trace = trace
38
38
  @dedup_identifiers = false
39
+ @lines_at = nil
39
40
  end
40
41
 
41
42
  def parse
@@ -48,9 +49,43 @@ module GraphQL
48
49
  end
49
50
  end
50
51
 
52
+ def line_at(pos)
53
+ line = lines_at.bsearch_index { |l| l >= pos }
54
+ if line.nil?
55
+ @lines_at.size + 1
56
+ else
57
+ line + 1
58
+ end
59
+ end
60
+
61
+ def column_at(pos)
62
+ next_line_idx = lines_at.bsearch_index { |l| l >= pos } || 0
63
+ if next_line_idx > 0
64
+ line_pos = @lines_at[next_line_idx - 1]
65
+ pos - line_pos
66
+ else
67
+ pos + 1
68
+ end
69
+ end
51
70
 
52
71
  private
53
72
 
73
+ # @return [Array<Integer>] Positions of each line break in the original string
74
+ def lines_at
75
+ @lines_at ||= begin
76
+ la = []
77
+ idx = 0
78
+ while idx
79
+ idx = @graphql_str.index("\n", idx)
80
+ if idx
81
+ la << idx
82
+ idx += 1
83
+ end
84
+ end
85
+ la
86
+ end
87
+ end
88
+
54
89
  attr_reader :token_name
55
90
 
56
91
  def advance_token
@@ -73,7 +108,7 @@ module GraphQL
73
108
  while !@lexer.eos?
74
109
  defns << definition
75
110
  end
76
- Document.new(pos: 0, definitions: defns, filename: @filename, source_string: @graphql_str)
111
+ Document.new(pos: 0, definitions: defns, filename: @filename, source: self)
77
112
  end
78
113
 
79
114
  def definition
@@ -95,7 +130,7 @@ module GraphQL
95
130
  directives: directives,
96
131
  selections: selections,
97
132
  filename: @filename,
98
- source_string: @graphql_str
133
+ source: self
99
134
  )
100
135
  when :QUERY, :MUTATION, :SUBSCRIPTION, :LCURLY
101
136
  op_loc = pos
@@ -131,7 +166,7 @@ module GraphQL
131
166
  default_value: default_value,
132
167
  directives: directives,
133
168
  filename: @filename,
134
- source_string: @graphql_str
169
+ source: self
135
170
  )
136
171
  end
137
172
  expect_token(:RPAREN)
@@ -150,7 +185,7 @@ module GraphQL
150
185
  directives: directives,
151
186
  selections: selection_set,
152
187
  filename: @filename,
153
- source_string: @graphql_str
188
+ source: self
154
189
  )
155
190
  when :EXTEND
156
191
  loc = pos
@@ -160,7 +195,7 @@ module GraphQL
160
195
  advance_token
161
196
  name = parse_name
162
197
  directives = parse_directives
163
- ScalarTypeExtension.new(pos: loc, name: name, directives: directives, filename: @filename, source_string: @graphql_str)
198
+ ScalarTypeExtension.new(pos: loc, name: name, directives: directives, filename: @filename, source: self)
164
199
  when :TYPE
165
200
  advance_token
166
201
  name = parse_name
@@ -168,32 +203,32 @@ module GraphQL
168
203
  directives = parse_directives
169
204
  field_defns = at?(:LCURLY) ? parse_field_definitions : EMPTY_ARRAY
170
205
 
171
- ObjectTypeExtension.new(pos: loc, name: name, interfaces: implements_interfaces, directives: directives, fields: field_defns, filename: @filename, source_string: @graphql_str)
206
+ ObjectTypeExtension.new(pos: loc, name: name, interfaces: implements_interfaces, directives: directives, fields: field_defns, filename: @filename, source: self)
172
207
  when :INTERFACE
173
208
  advance_token
174
209
  name = parse_name
175
210
  directives = parse_directives
176
211
  interfaces = parse_implements
177
212
  fields_definition = at?(:LCURLY) ? parse_field_definitions : EMPTY_ARRAY
178
- InterfaceTypeExtension.new(pos: loc, name: name, directives: directives, fields: fields_definition, interfaces: interfaces, filename: @filename, source_string: @graphql_str)
213
+ InterfaceTypeExtension.new(pos: loc, name: name, directives: directives, fields: fields_definition, interfaces: interfaces, filename: @filename, source: self)
179
214
  when :UNION
180
215
  advance_token
181
216
  name = parse_name
182
217
  directives = parse_directives
183
218
  union_member_types = parse_union_members
184
- UnionTypeExtension.new(pos: loc, name: name, directives: directives, types: union_member_types, filename: @filename, source_string: @graphql_str)
219
+ UnionTypeExtension.new(pos: loc, name: name, directives: directives, types: union_member_types, filename: @filename, source: self)
185
220
  when :ENUM
186
221
  advance_token
187
222
  name = parse_name
188
223
  directives = parse_directives
189
224
  enum_values_definition = parse_enum_value_definitions
190
- Nodes::EnumTypeExtension.new(pos: loc, name: name, directives: directives, values: enum_values_definition, filename: @filename, source_string: @graphql_str)
225
+ Nodes::EnumTypeExtension.new(pos: loc, name: name, directives: directives, values: enum_values_definition, filename: @filename, source: self)
191
226
  when :INPUT
192
227
  advance_token
193
228
  name = parse_name
194
229
  directives = parse_directives
195
230
  input_fields_definition = parse_input_object_field_definitions
196
- InputObjectTypeExtension.new(pos: loc, name: name, directives: directives, fields: input_fields_definition, filename: @filename, source_string: @graphql_str)
231
+ InputObjectTypeExtension.new(pos: loc, name: name, directives: directives, fields: input_fields_definition, filename: @filename, source: self)
197
232
  when :SCHEMA
198
233
  advance_token
199
234
  directives = parse_directives
@@ -226,7 +261,7 @@ module GraphQL
226
261
  directives: directives,
227
262
  pos: loc,
228
263
  filename: @filename,
229
- source_string: @graphql_str,
264
+ source: self,
230
265
  )
231
266
  else
232
267
  expect_one_of([:SCHEMA, :SCALAR, :TYPE, :ENUM, :INPUT, :UNION, :INTERFACE])
@@ -259,7 +294,7 @@ module GraphQL
259
294
  end
260
295
  end
261
296
  expect_token :RCURLY
262
- SchemaDefinition.new(pos: loc, definition_pos: defn_loc, query: query, mutation: mutation, subscription: subscription, directives: directives, filename: @filename, source_string: @graphql_str)
297
+ SchemaDefinition.new(pos: loc, definition_pos: defn_loc, query: query, mutation: mutation, subscription: subscription, directives: directives, filename: @filename, source: self)
263
298
  when :DIRECTIVE
264
299
  advance_token
265
300
  expect_token :DIR_SIGN
@@ -272,12 +307,12 @@ module GraphQL
272
307
  false
273
308
  end
274
309
  expect_token :ON
275
- directive_locations = [DirectiveLocation.new(pos: pos, name: parse_name, filename: @filename, source_string: @graphql_str)]
310
+ directive_locations = [DirectiveLocation.new(pos: pos, name: parse_name, filename: @filename, source: self)]
276
311
  while at?(:PIPE)
277
312
  advance_token
278
- directive_locations << DirectiveLocation.new(pos: pos, name: parse_name, filename: @filename, source_string: @graphql_str)
313
+ directive_locations << DirectiveLocation.new(pos: pos, name: parse_name, filename: @filename, source: self)
279
314
  end
280
- DirectiveDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, arguments: arguments_definition, locations: directive_locations, repeatable: repeatable, filename: @filename, source_string: @graphql_str)
315
+ DirectiveDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, arguments: arguments_definition, locations: directive_locations, repeatable: repeatable, filename: @filename, source: self)
281
316
  when :TYPE
282
317
  advance_token
283
318
  name = parse_name
@@ -285,37 +320,37 @@ module GraphQL
285
320
  directives = parse_directives
286
321
  field_defns = at?(:LCURLY) ? parse_field_definitions : EMPTY_ARRAY
287
322
 
288
- ObjectTypeDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, interfaces: implements_interfaces, directives: directives, fields: field_defns, filename: @filename, source_string: @graphql_str)
323
+ ObjectTypeDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, interfaces: implements_interfaces, directives: directives, fields: field_defns, filename: @filename, source: self)
289
324
  when :INTERFACE
290
325
  advance_token
291
326
  name = parse_name
292
327
  interfaces = parse_implements
293
328
  directives = parse_directives
294
329
  fields_definition = parse_field_definitions
295
- InterfaceTypeDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, directives: directives, fields: fields_definition, interfaces: interfaces, filename: @filename, source_string: @graphql_str)
330
+ InterfaceTypeDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, directives: directives, fields: fields_definition, interfaces: interfaces, filename: @filename, source: self)
296
331
  when :UNION
297
332
  advance_token
298
333
  name = parse_name
299
334
  directives = parse_directives
300
335
  union_member_types = parse_union_members
301
- UnionTypeDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, directives: directives, types: union_member_types, filename: @filename, source_string: @graphql_str)
336
+ UnionTypeDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, directives: directives, types: union_member_types, filename: @filename, source: self)
302
337
  when :SCALAR
303
338
  advance_token
304
339
  name = parse_name
305
340
  directives = parse_directives
306
- ScalarTypeDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, directives: directives, filename: @filename, source_string: @graphql_str)
341
+ ScalarTypeDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, directives: directives, filename: @filename, source: self)
307
342
  when :ENUM
308
343
  advance_token
309
344
  name = parse_name
310
345
  directives = parse_directives
311
346
  enum_values_definition = parse_enum_value_definitions
312
- Nodes::EnumTypeDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, directives: directives, values: enum_values_definition, filename: @filename, source_string: @graphql_str)
347
+ Nodes::EnumTypeDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, directives: directives, values: enum_values_definition, filename: @filename, source: self)
313
348
  when :INPUT
314
349
  advance_token
315
350
  name = parse_name
316
351
  directives = parse_directives
317
352
  input_fields_definition = parse_input_object_field_definitions
318
- InputObjectTypeDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, directives: directives, fields: input_fields_definition, filename: @filename, source_string: @graphql_str)
353
+ InputObjectTypeDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, directives: directives, fields: input_fields_definition, filename: @filename, source: self)
319
354
  else
320
355
  expect_one_of([:SCHEMA, :SCALAR, :TYPE, :ENUM, :INPUT, :UNION, :INTERFACE])
321
356
  end
@@ -346,7 +381,7 @@ module GraphQL
346
381
  defn_loc = pos
347
382
  enum_value = parse_enum_name
348
383
  v_directives = parse_directives
349
- list << EnumValueDefinition.new(pos: v_loc, definition_pos: defn_loc, description: description, name: enum_value, directives: v_directives, filename: @filename, source_string: @graphql_str)
384
+ list << EnumValueDefinition.new(pos: v_loc, definition_pos: defn_loc, description: description, name: enum_value, directives: v_directives, filename: @filename, source: self)
350
385
  end
351
386
  expect_token :RCURLY
352
387
  list
@@ -397,7 +432,7 @@ module GraphQL
397
432
  type = self.type
398
433
  directives = parse_directives
399
434
 
400
- list << FieldDefinition.new(pos: loc, definition_pos: defn_loc, description: description, name: name, arguments: arguments_definition, type: type, directives: directives, filename: @filename, source_string: @graphql_str)
435
+ list << FieldDefinition.new(pos: loc, definition_pos: defn_loc, description: description, name: name, arguments: arguments_definition, type: type, directives: directives, filename: @filename, source: self)
401
436
  end
402
437
  expect_token :RCURLY
403
438
  list
@@ -431,7 +466,7 @@ module GraphQL
431
466
  nil
432
467
  end
433
468
  directives = parse_directives
434
- InputValueDefinition.new(pos: loc, definition_pos: defn_loc, description: description, name: name, type: type, default_value: default_value, directives: directives, filename: @filename, source_string: @graphql_str)
469
+ InputValueDefinition.new(pos: loc, definition_pos: defn_loc, description: description, name: name, type: type, default_value: default_value, directives: directives, filename: @filename, source: self)
435
470
  end
436
471
 
437
472
  def type
@@ -489,7 +524,7 @@ module GraphQL
489
524
 
490
525
  directives = parse_directives
491
526
 
492
- Nodes::InlineFragment.new(pos: loc, type: if_type, directives: directives, selections: selection_set, filename: @filename, source_string: @graphql_str)
527
+ Nodes::InlineFragment.new(pos: loc, type: if_type, directives: directives, selections: selection_set, filename: @filename, source: self)
493
528
  else
494
529
  name = parse_name_without_on
495
530
  directives = parse_directives
@@ -497,7 +532,7 @@ module GraphQL
497
532
  # Can this ever happen?
498
533
  # expect_token(:IDENTIFIER) if at?(:ON)
499
534
 
500
- FragmentSpread.new(pos: loc, name: name, directives: directives, filename: @filename, source_string: @graphql_str)
535
+ FragmentSpread.new(pos: loc, name: name, directives: directives, filename: @filename, source: self)
501
536
  end
502
537
  else
503
538
  loc = pos
@@ -515,7 +550,7 @@ module GraphQL
515
550
  directives = at?(:DIR_SIGN) ? parse_directives : nil
516
551
  selection_set = at?(:LCURLY) ? self.selection_set : nil
517
552
 
518
- Nodes::Field.new(pos: loc, field_alias: field_alias, name: name, arguments: arguments, directives: directives, selections: selection_set, filename: @filename, source_string: @graphql_str)
553
+ Nodes::Field.new(pos: loc, field_alias: field_alias, name: name, arguments: arguments, directives: directives, selections: selection_set, filename: @filename, source: self)
519
554
  end
520
555
  end
521
556
  expect_token(:RCURLY)
@@ -609,7 +644,7 @@ module GraphQL
609
644
  end
610
645
 
611
646
  def parse_type_name
612
- TypeName.new(pos: pos, name: parse_name, filename: @filename, source_string: @graphql_str)
647
+ TypeName.new(pos: pos, name: parse_name, filename: @filename, source: self)
613
648
  end
614
649
 
615
650
  def parse_directives
@@ -621,7 +656,7 @@ module GraphQL
621
656
  name = parse_name
622
657
  arguments = parse_arguments
623
658
 
624
- dirs << Nodes::Directive.new(pos: loc, name: name, arguments: arguments, filename: @filename, source_string: @graphql_str)
659
+ dirs << Nodes::Directive.new(pos: loc, name: name, arguments: arguments, filename: @filename, source: self)
625
660
  end
626
661
  dirs
627
662
  else
@@ -637,7 +672,7 @@ module GraphQL
637
672
  loc = pos
638
673
  name = parse_name
639
674
  expect_token(:COLON)
640
- args << Nodes::Argument.new(pos: loc, name: name, value: value, filename: @filename, source_string: @graphql_str)
675
+ args << Nodes::Argument.new(pos: loc, name: name, value: value, filename: @filename, source: self)
641
676
  end
642
677
  if args.empty?
643
678
  expect_token(:ARGUMENT_NAME) # At least one argument is required
@@ -671,9 +706,9 @@ module GraphQL
671
706
  false
672
707
  when :NULL
673
708
  advance_token
674
- NullValue.new(pos: pos, name: "null", filename: @filename, source_string: @graphql_str)
709
+ NullValue.new(pos: pos, name: "null", filename: @filename, source: self)
675
710
  when :IDENTIFIER
676
- Nodes::Enum.new(pos: pos, name: expect_token_value(:IDENTIFIER), filename: @filename, source_string: @graphql_str)
711
+ Nodes::Enum.new(pos: pos, name: expect_token_value(:IDENTIFIER), filename: @filename, source: self)
677
712
  when :LBRACKET
678
713
  advance_token
679
714
  list = []
@@ -690,14 +725,14 @@ module GraphQL
690
725
  loc = pos
691
726
  n = parse_name
692
727
  expect_token(:COLON)
693
- args << Argument.new(pos: loc, name: n, value: value, filename: @filename, source_string: @graphql_str)
728
+ args << Argument.new(pos: loc, name: n, value: value, filename: @filename, source: self)
694
729
  end
695
730
  expect_token(:RCURLY)
696
- InputObject.new(pos: start, arguments: args, filename: @filename, source_string: @graphql_str)
731
+ InputObject.new(pos: start, arguments: args, filename: @filename, source: self)
697
732
  when :VAR_SIGN
698
733
  loc = pos
699
734
  advance_token
700
- VariableIdentifier.new(pos: loc, name: parse_name, filename: @filename, source_string: @graphql_str)
735
+ VariableIdentifier.new(pos: loc, name: parse_name, filename: @filename, source: self)
701
736
  else
702
737
  expect_token(:VALUE)
703
738
  end
@@ -749,9 +749,10 @@ module GraphQL
749
749
 
750
750
  attr_writer :max_complexity
751
751
 
752
- def max_complexity(max_complexity = nil)
752
+ def max_complexity(max_complexity = nil, count_introspection_fields: true)
753
753
  if max_complexity
754
754
  @max_complexity = max_complexity
755
+ @max_complexity_count_introspection_fields = count_introspection_fields
755
756
  elsif defined?(@max_complexity)
756
757
  @max_complexity
757
758
  else
@@ -759,6 +760,14 @@ module GraphQL
759
760
  end
760
761
  end
761
762
 
763
+ def max_complexity_count_introspection_fields
764
+ if defined?(@max_complexity_count_introspection_fields)
765
+ @max_complexity_count_introspection_fields
766
+ else
767
+ find_inherited_value(:max_complexity_count_introspection_fields, true)
768
+ end
769
+ end
770
+
762
771
  attr_writer :analysis_engine
763
772
 
764
773
  def analysis_engine
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "2.3.2"
3
+ VERSION = "2.3.3"
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.3.2
4
+ version: 2.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-26 00:00:00.000000000 Z
11
+ date: 2024-05-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64