graphql 2.0.8 → 2.0.9

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: a10c35ffd2541c0b387e2e7d127eea0d1e2b4559fbd637288296369c0be09d0d
4
- data.tar.gz: 34bf4d3cc5ef08bfbc065f9cdff4690dfa4b3351d46e014422304b897b531189
3
+ metadata.gz: 39d95cd85a336ff82b22df87f496df97db11ecae05dbf80d090d5bb51445a499
4
+ data.tar.gz: b50ecc9d63922cbe1e7cbbd7d9a049528625584fb0bd6991918e867f8d6e2e45
5
5
  SHA512:
6
- metadata.gz: afed371861c1dcca740f07940d7f8239e800723623d6a9eb664592b169568ab1d92e3c2ea1286ba40625e00be0b27584f94e2493479cfd119251831d90c3f0a0
7
- data.tar.gz: 43e8362810fb7a48fcdec9f997a2b33c599e08c1276da79480e75c6fad456328775e71dc1317e98923a88b5e3169a5f9f3b491d09b943c49805d536071e0047f
6
+ metadata.gz: b404ea0ca0c0a1b4206330514da8d38c5e5f31abd4c93ebc696c91c2177f25e7f40703016742aeb6f8857f1bd208b9012778a21643a7ae08709bd08c994b31eb
7
+ data.tar.gz: 5d41fa5df69f4722bf0bffaca89675b77ff7cb4b1af863550bb5908e03135f82214f516c092b83273c3ff367d20c845a000db9d5bbf5f8e43a3db0a0640a0095
@@ -39,9 +39,11 @@ module GraphQL
39
39
  @used_deprecated_arguments << argument.definition.path
40
40
  end
41
41
 
42
+ next if argument.value.nil?
43
+
42
44
  if argument.definition.type.kind.input_object?
43
45
  extract_deprecated_arguments(argument.value.arguments.argument_values) # rubocop:disable Development/ContextIsPassedCop -- runtime args instance
44
- elsif argument.definition.type.list? && !argument.value.nil?
46
+ elsif argument.definition.type.list?
45
47
  argument
46
48
  .value
47
49
  .select { |value| value.respond_to?(:arguments) }
@@ -56,8 +56,9 @@ module GraphQL
56
56
  # @param last [Integer, nil] Limit parameter from the client, if provided
57
57
  # @param before [String, nil] A cursor for pagination, if the client provided one.
58
58
  # @param arguments [Hash] The arguments to the field that returned the collection wrapped by this connection
59
- # @param max_page_size [Integer, nil] A configured value to cap the result size. Applied as `first` if neither first or last are given.
60
- def initialize(items, parent: nil, field: nil, context: nil, first: nil, after: nil, max_page_size: :not_given, last: nil, before: nil, edge_class: nil, arguments: nil)
59
+ # @param max_page_size [Integer, nil] A configured value to cap the result size. Applied as `first` if neither first or last are given and no `default_page_size` is set.
60
+ # @param default_page_size [Integer, nil] A configured value to determine the result size when neither first or last are given.
61
+ def initialize(items, parent: nil, field: nil, context: nil, first: nil, after: nil, max_page_size: :not_given, default_page_size: :not_given, last: nil, before: nil, edge_class: nil, arguments: nil)
61
62
  @items = items
62
63
  @parent = parent
63
64
  @context = context
@@ -76,6 +77,12 @@ module GraphQL
76
77
  else
77
78
  max_page_size
78
79
  end
80
+ @has_default_page_size_override = default_page_size != :not_given
81
+ @default_page_size = if default_page_size == :not_given
82
+ nil
83
+ else
84
+ default_page_size
85
+ end
79
86
  end
80
87
 
81
88
  def max_page_size=(new_value)
@@ -95,16 +102,36 @@ module GraphQL
95
102
  @has_max_page_size_override
96
103
  end
97
104
 
105
+ def default_page_size=(new_value)
106
+ @has_default_page_size_override = true
107
+ @default_page_size = new_value
108
+ end
109
+
110
+ def default_page_size
111
+ if @has_default_page_size_override
112
+ @default_page_size
113
+ else
114
+ context.schema.default_page_size
115
+ end
116
+ end
117
+
118
+ def has_default_page_size_override?
119
+ @has_default_page_size_override
120
+ end
121
+
98
122
  attr_writer :first
99
123
  # @return [Integer, nil]
100
124
  # A clamped `first` value.
101
125
  # (The underlying instance variable doesn't have limits on it.)
102
- # If neither `first` nor `last` is given, but `max_page_size` is present, max_page_size is used for first.
126
+ # If neither `first` nor `last` is given, but `default_page_size` is
127
+ # present, default_page_size is used for first. If `default_page_size`
128
+ # is greater than `max_page_size``, it'll be clamped down to
129
+ # `max_page_size`. If `default_page_size` is nil, use `max_page_size`.
103
130
  def first
104
131
  @first ||= begin
105
132
  capped = limit_pagination_argument(@first_value, max_page_size)
106
133
  if capped.nil? && last.nil?
107
- capped = max_page_size
134
+ capped = limit_pagination_argument(default_page_size, max_page_size) || max_page_size
108
135
  end
109
136
  capped
110
137
  end
@@ -70,6 +70,7 @@ module GraphQL
70
70
  parent: parent,
71
71
  field: field,
72
72
  max_page_size: field.has_max_page_size? ? field.max_page_size : context.schema.default_max_page_size,
73
+ default_page_size: field.has_default_page_size? ? field.default_page_size : context.schema.default_page_size,
73
74
  first: arguments[:first],
74
75
  after: arguments[:after],
75
76
  last: arguments[:last],
@@ -47,6 +47,9 @@ module GraphQL
47
47
  if field.has_max_page_size? && !value.has_max_page_size_override?
48
48
  value.max_page_size = field.max_page_size
49
49
  end
50
+ if field.has_default_page_size? && !value.has_default_page_size_override?
51
+ value.default_page_size = field.default_page_size
52
+ end
50
53
  if context.schema.new_connections? && (custom_t = context.schema.connections.edge_class_for_field(@field))
51
54
  value.edge_class = custom_t
52
55
  end
@@ -64,6 +67,7 @@ module GraphQL
64
67
  original_arguments,
65
68
  field: field,
66
69
  max_page_size: field.max_page_size,
70
+ default_page_size: field.default_page_size,
67
71
  parent: object,
68
72
  context: context,
69
73
  )
@@ -200,6 +200,7 @@ module GraphQL
200
200
  # @param connection [Boolean] `true` if this field should get automagic connection behavior; default is to infer by `*Connection` in the return type name
201
201
  # @param connection_extension [Class] The extension to add, to implement connections. If `nil`, no extension is added.
202
202
  # @param max_page_size [Integer, nil] For connections, the maximum number of items to return from this field, or `nil` to allow unlimited results.
203
+ # @param default_page_size [Integer, nil] For connections, the default number of items to return from this field, or `nil` to return unlimited results.
203
204
  # @param introspection [Boolean] If true, this field will be marked as `#introspection?` and the name may begin with `__`
204
205
  # @param resolver_class [Class] (Private) A {Schema::Resolver} which this field was derived from. Use `resolver:` to create a field with a resolver.
205
206
  # @param arguments [{String=>GraphQL::Schema::Argument, Hash}] Arguments for this field (may be added in the block, also)
@@ -215,7 +216,7 @@ module GraphQL
215
216
  # @param method_conflict_warning [Boolean] If false, skip the warning if this field's method conflicts with a built-in method
216
217
  # @param validates [Array<Hash>] Configurations for validating this field
217
218
  # @fallback_value [Object] A fallback value if the method is not defined
218
- def initialize(type: nil, name: nil, owner: nil, null: nil, description: :not_given, deprecation_reason: nil, method: nil, hash_key: nil, dig: nil, resolver_method: nil, connection: nil, max_page_size: :not_given, scope: nil, introspection: false, camelize: true, trace: nil, complexity: nil, ast_node: nil, extras: EMPTY_ARRAY, extensions: EMPTY_ARRAY, connection_extension: self.class.connection_extension, resolver_class: nil, subscription_scope: nil, relay_node_field: false, relay_nodes_field: false, method_conflict_warning: true, broadcastable: nil, arguments: EMPTY_HASH, directives: EMPTY_HASH, validates: EMPTY_ARRAY, fallback_value: :not_given, &definition_block)
219
+ def initialize(type: nil, name: nil, owner: nil, null: nil, description: :not_given, deprecation_reason: nil, method: nil, hash_key: nil, dig: nil, resolver_method: nil, connection: nil, max_page_size: :not_given, default_page_size: :not_given, scope: nil, introspection: false, camelize: true, trace: nil, complexity: nil, ast_node: nil, extras: EMPTY_ARRAY, extensions: EMPTY_ARRAY, connection_extension: self.class.connection_extension, resolver_class: nil, subscription_scope: nil, relay_node_field: false, relay_nodes_field: false, method_conflict_warning: true, broadcastable: nil, arguments: EMPTY_HASH, directives: EMPTY_HASH, validates: EMPTY_ARRAY, fallback_value: :not_given, &definition_block)
219
220
  if name.nil?
220
221
  raise ArgumentError, "missing first `name` argument or keyword `name:`"
221
222
  end
@@ -269,6 +270,8 @@ module GraphQL
269
270
  @connection = connection
270
271
  @has_max_page_size = max_page_size != :not_given
271
272
  @max_page_size = max_page_size == :not_given ? nil : max_page_size
273
+ @has_default_page_size = default_page_size != :not_given
274
+ @default_page_size = default_page_size == :not_given ? nil : default_page_size
272
275
  @introspection = introspection
273
276
  @extras = extras
274
277
  if !broadcastable.nil?
@@ -464,11 +467,11 @@ module GraphQL
464
467
  end
465
468
 
466
469
  if max_possible_page_size.nil?
467
- max_possible_page_size = max_page_size || query.schema.default_max_page_size
470
+ max_possible_page_size = default_page_size || query.schema.default_page_size || max_page_size || query.schema.default_max_page_size
468
471
  end
469
472
 
470
473
  if max_possible_page_size.nil?
471
- raise GraphQL::Error, "Can't calculate complexity for #{path}, no `first:`, `last:`, `max_page_size` or `default_max_page_size`"
474
+ raise GraphQL::Error, "Can't calculate complexity for #{path}, no `first:`, `last:`, `default_page_size`, `max_page_size` or `default_max_page_size`"
472
475
  else
473
476
  metadata_complexity = 0
474
477
  lookahead = GraphQL::Execution::Lookahead.new(query: query, field: self, ast_nodes: nodes, owner_type: owner)
@@ -496,7 +499,13 @@ module GraphQL
496
499
  case defined_complexity
497
500
  when Proc
498
501
  arguments = query.arguments_for(nodes.first, self)
499
- defined_complexity.call(query.context, arguments.keyword_arguments, child_complexity)
502
+ if arguments.is_a?(GraphQL::ExecutionError)
503
+ return child_complexity
504
+ elsif arguments.respond_to?(:keyword_arguments)
505
+ arguments = arguments.keyword_arguments
506
+ end
507
+
508
+ defined_complexity.call(query.context, arguments, child_complexity)
500
509
  when Numeric
501
510
  defined_complexity + child_complexity
502
511
  else
@@ -539,6 +548,16 @@ module GraphQL
539
548
  @max_page_size || (@resolver_class && @resolver_class.max_page_size)
540
549
  end
541
550
 
551
+ # @return [Boolean] True if this field's {#default_page_size} should override the schema default.
552
+ def has_default_page_size?
553
+ @has_default_page_size || (@resolver_class && @resolver_class.has_default_page_size?)
554
+ end
555
+
556
+ # @return [Integer, nil] Applied to connections if {#has_default_page_size?}
557
+ def default_page_size
558
+ @default_page_size || (@resolver_class && @resolver_class.default_page_size)
559
+ end
560
+
542
561
  class MissingReturnTypeError < GraphQL::Error; end
543
562
  attr_writer :type
544
563
 
@@ -328,6 +328,27 @@ module GraphQL
328
328
  (!!defined?(@max_page_size)) || (superclass.respond_to?(:has_max_page_size?) && superclass.has_max_page_size?)
329
329
  end
330
330
 
331
+ # Get or set the `default_page_size:` which will be configured for fields using this resolver
332
+ # (`nil` means "unlimited default page size".)
333
+ # @param default_page_size [Integer, nil] Set a new value
334
+ # @return [Integer, nil] The `default_page_size` assigned to fields that use this resolver
335
+ def default_page_size(new_default_page_size = :not_given)
336
+ if new_default_page_size != :not_given
337
+ @default_page_size = new_default_page_size
338
+ elsif defined?(@default_page_size)
339
+ @default_page_size
340
+ elsif superclass.respond_to?(:default_page_size)
341
+ superclass.default_page_size
342
+ else
343
+ nil
344
+ end
345
+ end
346
+
347
+ # @return [Boolean] `true` if this resolver or a superclass has an assigned `default_page_size`
348
+ def has_default_page_size?
349
+ (!!defined?(@default_page_size)) || (superclass.respond_to?(:has_default_page_size?) && superclass.has_default_page_size?)
350
+ end
351
+
331
352
  # A non-normalized type configuration, without `null` applied
332
353
  def type_expr
333
354
  @type_expr || (superclass.respond_to?(:type_expr) ? superclass.type_expr : nil)
@@ -506,6 +506,14 @@ module GraphQL
506
506
  end
507
507
  end
508
508
 
509
+ def default_page_size(new_default_page_size = nil)
510
+ if new_default_page_size
511
+ @default_page_size = new_default_page_size
512
+ else
513
+ @default_page_size || find_inherited_value(:default_page_size)
514
+ end
515
+ end
516
+
509
517
  def query_execution_strategy(new_query_execution_strategy = nil)
510
518
  if new_query_execution_strategy
511
519
  @query_execution_strategy = new_query_execution_strategy
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ module Tracing
5
+ class OpenTelemetryTracing < PlatformTracing
6
+ self.platform_keys = {
7
+ 'lex' => 'graphql.lex',
8
+ 'parse' => 'graphql.parse',
9
+ 'validate' => 'graphql.validate',
10
+ 'analyze_query' => 'graphql.analyze_query',
11
+ 'analyze_multiplex' => 'graphql.analyze_multiplex',
12
+ 'execute_query' => 'graphql.execute_query',
13
+ 'execute_query_lazy' => 'graphql.execute_query_lazy',
14
+ 'execute_multiplex' => 'graphql.execute_multiplex'
15
+ }
16
+
17
+ def platform_trace(platform_key, key, data)
18
+ return yield if platform_key.nil?
19
+
20
+ tracer.in_span(platform_key, attributes: attributes_for(key, data)) do |span, _context|
21
+ yield.tap do |response|
22
+ errors = response[:errors]&.compact&.map { |e| e.to_h }&.to_json if key == 'validate'
23
+ unless errors.nil?
24
+ span.add_event(
25
+ 'graphql.validation.error',
26
+ attributes: {
27
+ 'message' => errors
28
+ }
29
+ )
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ def platform_field_key(type, field)
36
+ "#{type.graphql_name}.#{field.graphql_name}"
37
+ end
38
+
39
+ def platform_authorized_key(type)
40
+ "#{type.graphql_name}.authorized"
41
+ end
42
+
43
+ def platform_resolve_type_key(type)
44
+ "#{type.graphql_name}.resolve_type"
45
+ end
46
+
47
+ private
48
+
49
+ def tracer
50
+ OpenTelemetry::Instrumentation::GraphQL::Instrumentation.instance.tracer
51
+ end
52
+
53
+ def config
54
+ OpenTelemetry::Instrumentation::GraphQL::Instrumentation.instance.config
55
+ end
56
+
57
+ def platform_key_enabled?(ctx, key)
58
+ return false unless config[key]
59
+
60
+ ns = ctx.namespace(:opentelemetry)
61
+ return true if ns.empty? # restores original behavior so that keys are returned if tracing is not set in context.
62
+ return false unless ns.key?(key) && ns[key]
63
+
64
+ return true
65
+ end
66
+
67
+ def attributes_for(key, data)
68
+ attributes = {}
69
+ case key
70
+ when 'execute_query'
71
+ attributes['selected_operation_name'] = data[:query].selected_operation_name if data[:query].selected_operation_name
72
+ attributes['selected_operation_type'] = data[:query].selected_operation.operation_type
73
+ attributes['query_string'] = data[:query].query_string
74
+ end
75
+ attributes
76
+ end
77
+
78
+ def cached_platform_key(ctx, key, trace_phase)
79
+ cache = ctx.namespace(self.class)[:platform_key_cache] ||= {}
80
+
81
+ cache.fetch(key) do
82
+ cache[key] = if trace_phase == :field
83
+ return unless platform_key_enabled?(ctx, :enable_platform_field)
84
+
85
+ yield
86
+ elsif trace_phase == :authorized
87
+ return unless platform_key_enabled?(ctx, :enable_platform_authorized)
88
+
89
+ yield
90
+ elsif trace_phase == :resolve_type
91
+ return unless platform_key_enabled?(ctx, :enable_platform_resolve_type)
92
+
93
+ yield
94
+ else
95
+ raise "Unknown trace phase"
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -45,7 +45,7 @@ module GraphQL
45
45
 
46
46
  platform_key = if trace_field
47
47
  context = data.fetch(:query).context
48
- cached_platform_key(context, field) { platform_field_key(data[:owner], field) }
48
+ cached_platform_key(context, field, :field) { platform_field_key(data[:owner], field) }
49
49
  else
50
50
  nil
51
51
  end
@@ -61,14 +61,14 @@ module GraphQL
61
61
  when "authorized", "authorized_lazy"
62
62
  type = data.fetch(:type)
63
63
  context = data.fetch(:context)
64
- platform_key = cached_platform_key(context, type) { platform_authorized_key(type) }
64
+ platform_key = cached_platform_key(context, type, :authorized) { platform_authorized_key(type) }
65
65
  platform_trace(platform_key, key, data) do
66
66
  yield
67
67
  end
68
68
  when "resolve_type", "resolve_type_lazy"
69
69
  type = data.fetch(:type)
70
70
  context = data.fetch(:context)
71
- platform_key = cached_platform_key(context, type) { platform_resolve_type_key(type) }
71
+ platform_key = cached_platform_key(context, type, :resolve_type) { platform_resolve_type_key(type) }
72
72
  platform_trace(platform_key, key, data) do
73
73
  yield
74
74
  end
@@ -116,7 +116,7 @@ module GraphQL
116
116
  # If the key isn't present, the given block is called and the result is cached for `key`.
117
117
  #
118
118
  # @return [String]
119
- def cached_platform_key(ctx, key)
119
+ def cached_platform_key(ctx, key, trace_phase)
120
120
  cache = ctx.namespace(self.class)[:platform_key_cache] ||= {}
121
121
  cache.fetch(key) { cache[key] = yield }
122
122
  end
@@ -8,6 +8,7 @@ require "graphql/tracing/new_relic_tracing"
8
8
  require "graphql/tracing/scout_tracing"
9
9
  require "graphql/tracing/statsd_tracing"
10
10
  require "graphql/tracing/prometheus_tracing"
11
+ require "graphql/tracing/opentelemetry_tracing"
11
12
 
12
13
  if defined?(PrometheusExporter::Server)
13
14
  require "graphql/tracing/prometheus_tracing/graphql_collector"
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "2.0.8"
3
+ VERSION = "2.0.9"
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.8
4
+ version: 2.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-05-24 00:00:00.000000000 Z
11
+ date: 2022-05-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: benchmark-ips
@@ -538,6 +538,7 @@ files:
538
538
  - lib/graphql/tracing/data_dog_tracing.rb
539
539
  - lib/graphql/tracing/new_relic_tracing.rb
540
540
  - lib/graphql/tracing/notifications_tracing.rb
541
+ - lib/graphql/tracing/opentelemetry_tracing.rb
541
542
  - lib/graphql/tracing/platform_tracing.rb
542
543
  - lib/graphql/tracing/prometheus_tracing.rb
543
544
  - lib/graphql/tracing/prometheus_tracing/graphql_collector.rb