graphql 2.0.7 → 2.0.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/generators/graphql/relay.rb +3 -17
- data/lib/graphql/analysis/ast/field_usage.rb +3 -1
- data/lib/graphql/execution/interpreter/runtime.rb +23 -3
- data/lib/graphql/execution/lazy.rb +0 -7
- data/lib/graphql/language/lexer.rb +42 -25
- data/lib/graphql/language/lexer.rl +26 -6
- data/lib/graphql/language/parser.rb +338 -327
- data/lib/graphql/language/parser.y +12 -8
- data/lib/graphql/pagination/connection.rb +31 -4
- data/lib/graphql/pagination/connections.rb +1 -0
- data/lib/graphql/pagination/relation_connection.rb +2 -0
- data/lib/graphql/rake_task.rb +1 -0
- data/lib/graphql/schema/addition.rb +1 -1
- data/lib/graphql/schema/field/connection_extension.rb +4 -0
- data/lib/graphql/schema/field.rb +51 -14
- data/lib/graphql/schema/resolver.rb +21 -0
- data/lib/graphql/schema.rb +15 -1
- data/lib/graphql/subscriptions.rb +1 -1
- data/lib/graphql/tracing/data_dog_tracing.rb +9 -0
- data/lib/graphql/tracing/platform_tracing.rb +21 -20
- data/lib/graphql/types/iso_8601_date_time.rb +3 -0
- data/lib/graphql/version.rb +1 -1
- metadata +3 -3
@@ -321,13 +321,13 @@ rule
|
|
321
321
|
|
322
322
|
object_type_extension:
|
323
323
|
/* TODO - This first one shouldn't be necessary but parser is getting confused */
|
324
|
-
EXTEND TYPE name implements
|
325
|
-
| EXTEND TYPE name implements_opt directives_list_opt
|
324
|
+
EXTEND TYPE name implements field_definition_list_opt { result = make_node(:ObjectTypeExtension, name: val[2], interfaces: val[3], directives: [], fields: val[4], position_source: val[0]) }
|
325
|
+
| EXTEND TYPE name implements_opt directives_list_opt field_definition_list_opt { result = make_node(:ObjectTypeExtension, name: val[2], interfaces: val[3], directives: val[4], fields: val[5], position_source: val[0]) }
|
326
326
|
| EXTEND TYPE name implements_opt directives_list { result = make_node(:ObjectTypeExtension, name: val[2], interfaces: val[3], directives: val[4], fields: [], position_source: val[0]) }
|
327
327
|
| EXTEND TYPE name implements { result = make_node(:ObjectTypeExtension, name: val[2], interfaces: val[3], directives: [], fields: [], position_source: val[0]) }
|
328
328
|
|
329
329
|
interface_type_extension:
|
330
|
-
EXTEND INTERFACE name implements_opt directives_list_opt
|
330
|
+
EXTEND INTERFACE name implements_opt directives_list_opt field_definition_list_opt { result = make_node(:InterfaceTypeExtension, name: val[2], interfaces: val[3], directives: val[4], fields: val[5], position_source: val[0]) }
|
331
331
|
| EXTEND INTERFACE name implements_opt directives_list { result = make_node(:InterfaceTypeExtension, name: val[2], interfaces: val[3], directives: val[4], fields: [], position_source: val[0]) }
|
332
332
|
| EXTEND INTERFACE name implements { result = make_node(:InterfaceTypeExtension, name: val[2], interfaces: val[3], directives: [], fields: [], position_source: val[0]) }
|
333
333
|
|
@@ -355,8 +355,8 @@ rule
|
|
355
355
|
}
|
356
356
|
|
357
357
|
object_type_definition:
|
358
|
-
description_opt TYPE name implements_opt directives_list_opt
|
359
|
-
result = make_node(:ObjectTypeDefinition, name: val[2], interfaces: val[3], directives: val[4], fields: val[
|
358
|
+
description_opt TYPE name implements_opt directives_list_opt field_definition_list_opt {
|
359
|
+
result = make_node(:ObjectTypeDefinition, name: val[2], interfaces: val[3], directives: val[4], fields: val[5], description: val[0] || get_description(val[1]), definition_line: val[1].line, position_source: val[0] || val[1])
|
360
360
|
}
|
361
361
|
|
362
362
|
implements_opt:
|
@@ -394,14 +394,18 @@ rule
|
|
394
394
|
result = make_node(:FieldDefinition, name: val[1], arguments: val[2], type: val[4], directives: val[5], description: val[0] || get_description(val[1]), definition_line: val[1].line, position_source: val[0] || val[1])
|
395
395
|
}
|
396
396
|
|
397
|
-
|
397
|
+
field_definition_list_opt:
|
398
398
|
/* none */ { result = EMPTY_ARRAY }
|
399
|
+
| LCURLY field_definition_list RCURLY { result = val[1] }
|
400
|
+
|
401
|
+
field_definition_list:
|
402
|
+
/* none - this is not actually valid but graphql-ruby used to print this */ { result = EMPTY_ARRAY }
|
399
403
|
| field_definition { result = [val[0]] }
|
400
404
|
| field_definition_list field_definition { val[0] << val[1] }
|
401
405
|
|
402
406
|
interface_type_definition:
|
403
|
-
description_opt INTERFACE name implements_opt directives_list_opt
|
404
|
-
result = make_node(:InterfaceTypeDefinition, name: val[2], interfaces: val[3], directives: val[4], fields: val[
|
407
|
+
description_opt INTERFACE name implements_opt directives_list_opt field_definition_list_opt {
|
408
|
+
result = make_node(:InterfaceTypeDefinition, name: val[2], interfaces: val[3], directives: val[4], fields: val[5], description: val[0] || get_description(val[1]), definition_line: val[1].line, position_source: val[0] || val[1])
|
405
409
|
}
|
406
410
|
|
407
411
|
union_members:
|
@@ -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
|
-
|
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 `
|
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],
|
data/lib/graphql/rake_task.rb
CHANGED
@@ -151,7 +151,7 @@ module GraphQL
|
|
151
151
|
um << owner
|
152
152
|
end
|
153
153
|
|
154
|
-
if (prev_type = get_local_type(type.graphql_name)) && prev_type == type
|
154
|
+
if (prev_type = get_local_type(type.graphql_name)) && (prev_type == type || (prev_type.is_a?(Array) && prev_type.include?(type)))
|
155
155
|
# No need to re-visit
|
156
156
|
elsif type.is_a?(Class) && type < GraphQL::Schema::Directive
|
157
157
|
@directives << type
|
@@ -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
|
)
|
data/lib/graphql/schema/field.rb
CHANGED
@@ -181,6 +181,8 @@ module GraphQL
|
|
181
181
|
|
182
182
|
# @return Boolean
|
183
183
|
attr_reader :relay_node_field
|
184
|
+
# @return Boolean
|
185
|
+
attr_reader :relay_nodes_field
|
184
186
|
|
185
187
|
# @return [Boolean] Should we warn if this field's name conflicts with a built-in method?
|
186
188
|
def method_conflict_warning?
|
@@ -200,6 +202,7 @@ module GraphQL
|
|
200
202
|
# @param connection [Boolean] `true` if this field should get automagic connection behavior; default is to infer by `*Connection` in the return type name
|
201
203
|
# @param connection_extension [Class] The extension to add, to implement connections. If `nil`, no extension is added.
|
202
204
|
# @param max_page_size [Integer, nil] For connections, the maximum number of items to return from this field, or `nil` to allow unlimited results.
|
205
|
+
# @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
206
|
# @param introspection [Boolean] If true, this field will be marked as `#introspection?` and the name may begin with `__`
|
204
207
|
# @param resolver_class [Class] (Private) A {Schema::Resolver} which this field was derived from. Use `resolver:` to create a field with a resolver.
|
205
208
|
# @param arguments [{String=>GraphQL::Schema::Argument, Hash}] Arguments for this field (may be added in the block, also)
|
@@ -214,7 +217,8 @@ module GraphQL
|
|
214
217
|
# @param ast_node [Language::Nodes::FieldDefinition, nil] If this schema was parsed from definition, this AST node defined the field
|
215
218
|
# @param method_conflict_warning [Boolean] If false, skip the warning if this field's method conflicts with a built-in method
|
216
219
|
# @param validates [Array<Hash>] Configurations for validating this field
|
217
|
-
|
220
|
+
# @fallback_value [Object] A fallback value if the method is not defined
|
221
|
+
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)
|
218
222
|
if name.nil?
|
219
223
|
raise ArgumentError, "missing first `name` argument or keyword `name:`"
|
220
224
|
end
|
@@ -246,7 +250,7 @@ module GraphQL
|
|
246
250
|
end
|
247
251
|
end
|
248
252
|
|
249
|
-
method_name = method || name_s
|
253
|
+
method_name = method || hash_key || name_s
|
250
254
|
@dig_keys = dig
|
251
255
|
if hash_key
|
252
256
|
@hash_key = hash_key
|
@@ -268,6 +272,8 @@ module GraphQL
|
|
268
272
|
@connection = connection
|
269
273
|
@has_max_page_size = max_page_size != :not_given
|
270
274
|
@max_page_size = max_page_size == :not_given ? nil : max_page_size
|
275
|
+
@has_default_page_size = default_page_size != :not_given
|
276
|
+
@default_page_size = default_page_size == :not_given ? nil : default_page_size
|
271
277
|
@introspection = introspection
|
272
278
|
@extras = extras
|
273
279
|
if !broadcastable.nil?
|
@@ -280,6 +286,7 @@ module GraphQL
|
|
280
286
|
@relay_nodes_field = relay_nodes_field
|
281
287
|
@ast_node = ast_node
|
282
288
|
@method_conflict_warning = method_conflict_warning
|
289
|
+
@fallback_value = fallback_value
|
283
290
|
|
284
291
|
arguments.each do |name, arg|
|
285
292
|
case arg
|
@@ -462,11 +469,11 @@ module GraphQL
|
|
462
469
|
end
|
463
470
|
|
464
471
|
if max_possible_page_size.nil?
|
465
|
-
max_possible_page_size = max_page_size || query.schema.default_max_page_size
|
472
|
+
max_possible_page_size = default_page_size || query.schema.default_page_size || max_page_size || query.schema.default_max_page_size
|
466
473
|
end
|
467
474
|
|
468
475
|
if max_possible_page_size.nil?
|
469
|
-
raise GraphQL::Error, "Can't calculate complexity for #{path}, no `first:`, `last:`, `max_page_size` or `default_max_page_size`"
|
476
|
+
raise GraphQL::Error, "Can't calculate complexity for #{path}, no `first:`, `last:`, `default_page_size`, `max_page_size` or `default_max_page_size`"
|
470
477
|
else
|
471
478
|
metadata_complexity = 0
|
472
479
|
lookahead = GraphQL::Execution::Lookahead.new(query: query, field: self, ast_nodes: nodes, owner_type: owner)
|
@@ -494,7 +501,13 @@ module GraphQL
|
|
494
501
|
case defined_complexity
|
495
502
|
when Proc
|
496
503
|
arguments = query.arguments_for(nodes.first, self)
|
497
|
-
|
504
|
+
if arguments.is_a?(GraphQL::ExecutionError)
|
505
|
+
return child_complexity
|
506
|
+
elsif arguments.respond_to?(:keyword_arguments)
|
507
|
+
arguments = arguments.keyword_arguments
|
508
|
+
end
|
509
|
+
|
510
|
+
defined_complexity.call(query.context, arguments, child_complexity)
|
498
511
|
when Numeric
|
499
512
|
defined_complexity + child_complexity
|
500
513
|
else
|
@@ -537,6 +550,16 @@ module GraphQL
|
|
537
550
|
@max_page_size || (@resolver_class && @resolver_class.max_page_size)
|
538
551
|
end
|
539
552
|
|
553
|
+
# @return [Boolean] True if this field's {#default_page_size} should override the schema default.
|
554
|
+
def has_default_page_size?
|
555
|
+
@has_default_page_size || (@resolver_class && @resolver_class.has_default_page_size?)
|
556
|
+
end
|
557
|
+
|
558
|
+
# @return [Integer, nil] Applied to connections if {#has_default_page_size?}
|
559
|
+
def default_page_size
|
560
|
+
@default_page_size || (@resolver_class && @resolver_class.default_page_size)
|
561
|
+
end
|
562
|
+
|
540
563
|
class MissingReturnTypeError < GraphQL::Error; end
|
541
564
|
attr_writer :type
|
542
565
|
|
@@ -643,11 +666,7 @@ module GraphQL
|
|
643
666
|
inner_object = obj.object
|
644
667
|
|
645
668
|
if defined?(@hash_key)
|
646
|
-
inner_object
|
647
|
-
inner_object[@hash_key_str]
|
648
|
-
}
|
649
|
-
elsif @dig_keys
|
650
|
-
inner_object.dig(*@dig_keys)
|
669
|
+
inner_object[@hash_key] || inner_object[@hash_key_str] || (@fallback_value != :not_given ? @fallback_value : nil)
|
651
670
|
elsif obj.respond_to?(resolver_method)
|
652
671
|
method_to_call = resolver_method
|
653
672
|
method_receiver = obj
|
@@ -658,10 +677,26 @@ module GraphQL
|
|
658
677
|
obj.public_send(resolver_method)
|
659
678
|
end
|
660
679
|
elsif inner_object.is_a?(Hash)
|
661
|
-
if
|
680
|
+
if @dig_keys
|
681
|
+
inner_object.dig(*@dig_keys)
|
682
|
+
elsif defined?(@hash_key)
|
683
|
+
if inner_object.key?(@hash_key)
|
684
|
+
inner_object[@hash_key]
|
685
|
+
elsif inner_object.key?(@hash_key_str)
|
686
|
+
inner_object[@hash_key_str]
|
687
|
+
elsif @fallback_value != :not_given
|
688
|
+
@fallback_value
|
689
|
+
else
|
690
|
+
nil
|
691
|
+
end
|
692
|
+
elsif inner_object.key?(@method_sym)
|
662
693
|
inner_object[@method_sym]
|
663
|
-
|
694
|
+
elsif inner_object.key?(@method_str)
|
664
695
|
inner_object[@method_str]
|
696
|
+
elsif @fallback_value != :not_given
|
697
|
+
@fallback_value
|
698
|
+
else
|
699
|
+
nil
|
665
700
|
end
|
666
701
|
elsif inner_object.respond_to?(@method_sym)
|
667
702
|
method_to_call = @method_sym
|
@@ -671,6 +706,8 @@ module GraphQL
|
|
671
706
|
else
|
672
707
|
inner_object.public_send(@method_sym)
|
673
708
|
end
|
709
|
+
elsif @fallback_value != :not_given
|
710
|
+
@fallback_value
|
674
711
|
else
|
675
712
|
raise <<-ERR
|
676
713
|
Failed to implement #{@owner.graphql_name}.#{@name}, tried:
|
@@ -679,7 +716,7 @@ module GraphQL
|
|
679
716
|
- `#{inner_object.class}##{@method_sym}`, which did not exist
|
680
717
|
- Looking up hash key `#{@method_sym.inspect}` or `#{@method_str.inspect}` on `#{inner_object}`, but it wasn't a Hash
|
681
718
|
|
682
|
-
To implement this field, define one of the methods above (and check for typos)
|
719
|
+
To implement this field, define one of the methods above (and check for typos), or supply a `fallback_value`.
|
683
720
|
ERR
|
684
721
|
end
|
685
722
|
end
|
@@ -751,7 +788,7 @@ module GraphQL
|
|
751
788
|
|
752
789
|
if unsatisfied_ruby_kwargs.any? || unsatisfied_method_params.any?
|
753
790
|
raise FieldImplementationFailed.new, <<-ERR
|
754
|
-
Failed to call
|
791
|
+
Failed to call `#{method_name.inspect}` on #{receiver.inspect} because the Ruby method params were incompatible with the GraphQL arguments:
|
755
792
|
|
756
793
|
#{ unsatisfied_ruby_kwargs
|
757
794
|
.map { |key, value| "- `#{key}: #{value}` was given by GraphQL but not defined in the Ruby method. Add `#{key}:` to the method parameters." }
|
@@ -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)
|
data/lib/graphql/schema.rb
CHANGED
@@ -132,7 +132,13 @@ module GraphQL
|
|
132
132
|
end
|
133
133
|
|
134
134
|
# @return [GraphQL::Subscriptions]
|
135
|
-
|
135
|
+
def subscriptions(inherited: true)
|
136
|
+
defined?(@subscriptions) ? @subscriptions : (inherited ? find_inherited_value(:subscriptions, nil) : nil)
|
137
|
+
end
|
138
|
+
|
139
|
+
def subscriptions=(new_implementation)
|
140
|
+
@subscriptions = new_implementation
|
141
|
+
end
|
136
142
|
|
137
143
|
# Returns the JSON response of {Introspection::INTROSPECTION_QUERY}.
|
138
144
|
# @see {#as_json}
|
@@ -506,6 +512,14 @@ module GraphQL
|
|
506
512
|
end
|
507
513
|
end
|
508
514
|
|
515
|
+
def default_page_size(new_default_page_size = nil)
|
516
|
+
if new_default_page_size
|
517
|
+
@default_page_size = new_default_page_size
|
518
|
+
else
|
519
|
+
@default_page_size || find_inherited_value(:default_page_size)
|
520
|
+
end
|
521
|
+
end
|
522
|
+
|
509
523
|
def query_execution_strategy(new_query_execution_strategy = nil)
|
510
524
|
if new_query_execution_strategy
|
511
525
|
@query_execution_strategy = new_query_execution_strategy
|
@@ -26,7 +26,7 @@ module GraphQL
|
|
26
26
|
def self.use(defn, options = {})
|
27
27
|
schema = defn.is_a?(Class) ? defn : defn.target
|
28
28
|
|
29
|
-
if schema.subscriptions
|
29
|
+
if schema.subscriptions(inherited: false)
|
30
30
|
raise ArgumentError, "Can't reinstall subscriptions. #{schema} is using #{schema.subscriptions}, can't also add #{self}"
|
31
31
|
end
|
32
32
|
|
@@ -45,6 +45,8 @@ module GraphQL
|
|
45
45
|
span.set_tag(:query_string, data[:query].query_string)
|
46
46
|
end
|
47
47
|
|
48
|
+
prepare_span(key, data, span)
|
49
|
+
|
48
50
|
yield
|
49
51
|
end
|
50
52
|
end
|
@@ -53,6 +55,13 @@ module GraphQL
|
|
53
55
|
options.fetch(:service, 'ruby-graphql')
|
54
56
|
end
|
55
57
|
|
58
|
+
# Implement this method in a subclass to apply custom tags to datadog spans
|
59
|
+
# @param key [String] The event being traced
|
60
|
+
# @param data [Hash] The runtime data for this event (@see GraphQL::Tracing for keys for each event)
|
61
|
+
# @param span [Datadog::Tracing::SpanOperation] The datadog span for this event
|
62
|
+
def prepare_span(key, data, span)
|
63
|
+
end
|
64
|
+
|
56
65
|
def tracer
|
57
66
|
default_tracer = defined?(Datadog::Tracing) ? Datadog::Tracing : Datadog.tracer
|
58
67
|
|
@@ -10,6 +10,10 @@ module GraphQL
|
|
10
10
|
class PlatformTracing
|
11
11
|
class << self
|
12
12
|
attr_accessor :platform_keys
|
13
|
+
|
14
|
+
def inherited(child_class)
|
15
|
+
child_class.platform_keys = self.platform_keys
|
16
|
+
end
|
13
17
|
end
|
14
18
|
|
15
19
|
def initialize(options = {})
|
@@ -26,25 +30,19 @@ module GraphQL
|
|
26
30
|
yield
|
27
31
|
end
|
28
32
|
when "execute_field", "execute_field_lazy"
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
+
field = data[:field]
|
34
|
+
return_type = field.type.unwrap
|
35
|
+
trace_field = if return_type.kind.scalar? || return_type.kind.enum?
|
36
|
+
(field.trace.nil? && @trace_scalars) || field.trace
|
33
37
|
else
|
34
|
-
|
35
|
-
|
36
|
-
trace_field = if return_type.kind.scalar? || return_type.kind.enum?
|
37
|
-
(field.trace.nil? && @trace_scalars) || field.trace
|
38
|
-
else
|
39
|
-
true
|
40
|
-
end
|
38
|
+
true
|
39
|
+
end
|
41
40
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
41
|
+
platform_key = if trace_field
|
42
|
+
context = data.fetch(:query).context
|
43
|
+
cached_platform_key(context, field, :field) { platform_field_key(data[:owner], field) }
|
44
|
+
else
|
45
|
+
nil
|
48
46
|
end
|
49
47
|
|
50
48
|
if platform_key && trace_field
|
@@ -57,14 +55,14 @@ module GraphQL
|
|
57
55
|
when "authorized", "authorized_lazy"
|
58
56
|
type = data.fetch(:type)
|
59
57
|
context = data.fetch(:context)
|
60
|
-
platform_key = cached_platform_key(context, type) { platform_authorized_key(type) }
|
58
|
+
platform_key = cached_platform_key(context, type, :authorized) { platform_authorized_key(type) }
|
61
59
|
platform_trace(platform_key, key, data) do
|
62
60
|
yield
|
63
61
|
end
|
64
62
|
when "resolve_type", "resolve_type_lazy"
|
65
63
|
type = data.fetch(:type)
|
66
64
|
context = data.fetch(:context)
|
67
|
-
platform_key = cached_platform_key(context, type) { platform_resolve_type_key(type) }
|
65
|
+
platform_key = cached_platform_key(context, type, :resolve_type) { platform_resolve_type_key(type) }
|
68
66
|
platform_trace(platform_key, key, data) do
|
69
67
|
yield
|
70
68
|
end
|
@@ -111,8 +109,11 @@ module GraphQL
|
|
111
109
|
#
|
112
110
|
# If the key isn't present, the given block is called and the result is cached for `key`.
|
113
111
|
#
|
112
|
+
# @param ctx [GraphQL::Query::Context]
|
113
|
+
# @param key [Class, GraphQL::Field] A part of the schema
|
114
|
+
# @param trace_phase [Symbol] The stage of execution being traced (used by OpenTelementry tracing)
|
114
115
|
# @return [String]
|
115
|
-
def cached_platform_key(ctx, key)
|
116
|
+
def cached_platform_key(ctx, key, trace_phase)
|
116
117
|
cache = ctx.namespace(self.class)[:platform_key_cache] ||= {}
|
117
118
|
cache.fetch(key) { cache[key] = yield }
|
118
119
|
end
|
@@ -60,6 +60,9 @@ module GraphQL
|
|
60
60
|
# But without this, it would zero out given any time part of `str_value` (hours and/or minutes)
|
61
61
|
if dt.iso8601.start_with?(str_value)
|
62
62
|
dt
|
63
|
+
elsif str_value.length == 8 && str_value.match?(/\A\d{8}\Z/)
|
64
|
+
# Allow dates that are missing the "-". eg. "20220404"
|
65
|
+
dt
|
63
66
|
else
|
64
67
|
nil
|
65
68
|
end
|
data/lib/graphql/version.rb
CHANGED
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.
|
4
|
+
version: 2.0.11
|
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-
|
11
|
+
date: 2022-06-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: benchmark-ips
|
@@ -595,7 +595,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
595
595
|
- !ruby/object:Gem::Version
|
596
596
|
version: '0'
|
597
597
|
requirements: []
|
598
|
-
rubygems_version: 3.2.
|
598
|
+
rubygems_version: 3.2.22
|
599
599
|
signing_key:
|
600
600
|
specification_version: 4
|
601
601
|
summary: A GraphQL language and runtime for Ruby
|