graphql 1.13.3 → 1.13.7
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/core.rb +0 -7
- data/lib/generators/graphql/enum_generator.rb +4 -10
- data/lib/generators/graphql/field_extractor.rb +31 -0
- data/lib/generators/graphql/input_generator.rb +50 -0
- data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
- data/lib/generators/graphql/{templates → install/templates}/base_mutation.erb +0 -0
- data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +0 -0
- data/lib/generators/graphql/install_generator.rb +1 -1
- data/lib/generators/graphql/interface_generator.rb +7 -7
- data/lib/generators/graphql/mutation_create_generator.rb +22 -0
- data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
- data/lib/generators/graphql/mutation_generator.rb +5 -30
- data/lib/generators/graphql/mutation_update_generator.rb +22 -0
- data/lib/generators/graphql/object_generator.rb +8 -37
- data/lib/generators/graphql/orm_mutations_base.rb +40 -0
- data/lib/generators/graphql/scalar_generator.rb +4 -2
- data/lib/generators/graphql/templates/enum.erb +5 -1
- data/lib/generators/graphql/templates/input.erb +9 -0
- data/lib/generators/graphql/templates/interface.erb +4 -2
- data/lib/generators/graphql/templates/mutation.erb +1 -1
- data/lib/generators/graphql/templates/mutation_create.erb +20 -0
- data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
- data/lib/generators/graphql/templates/mutation_update.erb +21 -0
- data/lib/generators/graphql/templates/object.erb +4 -2
- data/lib/generators/graphql/templates/scalar.erb +3 -1
- data/lib/generators/graphql/templates/union.erb +4 -2
- data/lib/generators/graphql/type_generator.rb +46 -9
- data/lib/generators/graphql/union_generator.rb +5 -5
- data/lib/graphql/analysis/ast/visitor.rb +2 -1
- data/lib/graphql/dataloader/source.rb +2 -2
- data/lib/graphql/date_encoding_error.rb +16 -0
- data/lib/graphql/execution/interpreter/arguments_cache.rb +4 -2
- data/lib/graphql/execution/interpreter/runtime.rb +33 -17
- data/lib/graphql/introspection/directive_location_enum.rb +2 -2
- data/lib/graphql/introspection/directive_type.rb +2 -0
- data/lib/graphql/introspection/schema_type.rb +5 -0
- data/lib/graphql/introspection/type_type.rb +9 -3
- data/lib/graphql/introspection.rb +3 -0
- data/lib/graphql/language/document_from_schema_definition.rb +1 -0
- data/lib/graphql/language/lexer.rb +50 -25
- data/lib/graphql/language/lexer.rl +2 -0
- data/lib/graphql/language/nodes.rb +1 -1
- data/lib/graphql/language/parser.rb +829 -816
- data/lib/graphql/language/parser.y +8 -2
- data/lib/graphql/language/printer.rb +4 -0
- data/lib/graphql/pagination/relation_connection.rb +8 -5
- data/lib/graphql/rubocop/graphql/default_required_true.rb +4 -4
- data/lib/graphql/schema/argument.rb +18 -1
- data/lib/graphql/schema/build_from_definition.rb +1 -0
- data/lib/graphql/schema/directive.rb +15 -0
- data/lib/graphql/schema/field.rb +13 -7
- data/lib/graphql/schema/loader.rb +3 -0
- data/lib/graphql/schema/scalar.rb +12 -0
- data/lib/graphql/schema.rb +12 -5
- data/lib/graphql/static_validation/base_visitor.rb +1 -1
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +1 -1
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +1 -1
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +1 -1
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +1 -1
- data/lib/graphql/static_validation/validation_context.rb +4 -0
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +1 -1
- data/lib/graphql/tracing/data_dog_tracing.rb +6 -1
- data/lib/graphql/tracing/platform_tracing.rb +11 -6
- data/lib/graphql/types/iso_8601_date.rb +13 -5
- data/lib/graphql/types/iso_8601_date_time.rb +8 -1
- data/lib/graphql/types/relay/connection_behaviors.rb +2 -1
- data/lib/graphql/types/relay/node_field.rb +0 -12
- data/lib/graphql/types/relay/nodes_field.rb +6 -0
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +12 -0
- metadata +20 -8
@@ -147,6 +147,7 @@ rule
|
|
147
147
|
name_without_on:
|
148
148
|
IDENTIFIER
|
149
149
|
| FRAGMENT
|
150
|
+
| REPEATABLE
|
150
151
|
| TRUE
|
151
152
|
| FALSE
|
152
153
|
| operation_type
|
@@ -155,6 +156,7 @@ rule
|
|
155
156
|
enum_name: /* any identifier, but not "true", "false" or "null" */
|
156
157
|
IDENTIFIER
|
157
158
|
| FRAGMENT
|
159
|
+
| REPEATABLE
|
158
160
|
| ON
|
159
161
|
| operation_type
|
160
162
|
| schema_keyword
|
@@ -422,10 +424,14 @@ rule
|
|
422
424
|
}
|
423
425
|
|
424
426
|
directive_definition:
|
425
|
-
description_opt DIRECTIVE DIR_SIGN name arguments_definitions_opt ON directive_locations {
|
426
|
-
result = make_node(:DirectiveDefinition, name: val[3], arguments: val[4], locations: val[
|
427
|
+
description_opt DIRECTIVE DIR_SIGN name arguments_definitions_opt directive_repeatable_opt ON directive_locations {
|
428
|
+
result = make_node(:DirectiveDefinition, name: val[3], arguments: val[4], locations: val[7], repeatable: !!val[5], description: val[0] || get_description(val[1]), definition_line: val[1].line, position_source: val[0] || val[1])
|
427
429
|
}
|
428
430
|
|
431
|
+
directive_repeatable_opt:
|
432
|
+
/* nothing */
|
433
|
+
| REPEATABLE
|
434
|
+
|
429
435
|
directive_locations:
|
430
436
|
name { result = [make_node(:DirectiveLocation, name: val[0].to_s, position_source: val[0])] }
|
431
437
|
| directive_locations PIPE name { val[0] << make_node(:DirectiveLocation, name: val[2].to_s, position_source: val[2]) }
|
@@ -47,7 +47,7 @@ module GraphQL
|
|
47
47
|
def cursor_for(item)
|
48
48
|
load_nodes
|
49
49
|
# index in nodes + existing offset + 1 (because it's offset, not index)
|
50
|
-
offset = nodes.index(item) + 1 + (@paged_nodes_offset || 0)
|
50
|
+
offset = nodes.index(item) + 1 + (@paged_nodes_offset || 0) - (relation_offset(items) || 0)
|
51
51
|
encode(offset.to_s)
|
52
52
|
end
|
53
53
|
|
@@ -116,9 +116,9 @@ module GraphQL
|
|
116
116
|
if defined?(@sliced_nodes_limit)
|
117
117
|
return
|
118
118
|
else
|
119
|
+
next_offset = relation_offset(items) || 0
|
119
120
|
if after_offset
|
120
|
-
|
121
|
-
relation_offset = previous_offset + after_offset
|
121
|
+
next_offset += after_offset
|
122
122
|
end
|
123
123
|
|
124
124
|
if before_offset && after_offset
|
@@ -136,7 +136,7 @@ module GraphQL
|
|
136
136
|
end
|
137
137
|
|
138
138
|
@sliced_nodes_limit = relation_limit
|
139
|
-
@sliced_nodes_offset =
|
139
|
+
@sliced_nodes_offset = next_offset
|
140
140
|
end
|
141
141
|
end
|
142
142
|
|
@@ -208,7 +208,10 @@ module GraphQL
|
|
208
208
|
@paged_nodes_offset = relation_offset
|
209
209
|
paginated_nodes = items
|
210
210
|
paginated_nodes = set_offset(paginated_nodes, relation_offset)
|
211
|
-
|
211
|
+
if relation_limit
|
212
|
+
paginated_nodes = set_limit(paginated_nodes, relation_limit)
|
213
|
+
end
|
214
|
+
paginated_nodes
|
212
215
|
end
|
213
216
|
end
|
214
217
|
|
@@ -25,16 +25,16 @@ module GraphQL
|
|
25
25
|
|
26
26
|
def_node_matcher :argument_config_with_required_true?, <<-Pattern
|
27
27
|
(
|
28
|
-
send nil? :argument ... (hash <$(pair (sym :required) (true)) ...>)
|
28
|
+
send {nil? _} :argument ... (hash <$(pair (sym :required) (true)) ...>)
|
29
29
|
)
|
30
30
|
Pattern
|
31
31
|
|
32
32
|
def on_send(node)
|
33
33
|
argument_config_with_required_true?(node) do |required_config|
|
34
34
|
add_offense(required_config) do |corrector|
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
cleaned_node_source = source_without_keyword_argument(node, required_config)
|
36
|
+
corrector.replace(node, cleaned_node_source)
|
37
|
+
end
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
@@ -48,13 +48,21 @@ module GraphQL
|
|
48
48
|
# @param directives [Hash{Class => Hash}]
|
49
49
|
# @param deprecation_reason [String]
|
50
50
|
# @param validates [Hash, nil] Options for building validators, if any should be applied
|
51
|
-
|
51
|
+
# @param replace_null_with_default [Boolean] if `true`, incoming values of `null` will be replaced with the configured `default_value`
|
52
|
+
def initialize(arg_name = nil, type_expr = nil, desc = nil, required: true, type: nil, name: nil, loads: nil, description: nil, ast_node: nil, default_value: NO_DEFAULT, as: nil, from_resolver: false, camelize: true, prepare: nil, method_access: true, owner:, validates: nil, directives: nil, deprecation_reason: nil, replace_null_with_default: false, &definition_block)
|
52
53
|
arg_name ||= name
|
53
54
|
@name = -(camelize ? Member::BuildType.camelize(arg_name.to_s) : arg_name.to_s)
|
54
55
|
@type_expr = type_expr || type
|
55
56
|
@description = desc || description
|
56
57
|
@null = required != true
|
57
58
|
@default_value = default_value
|
59
|
+
if replace_null_with_default
|
60
|
+
if !default_value?
|
61
|
+
raise ArgumentError, "`replace_null_with_default: true` requires a default value, please provide one with `default_value: ...`"
|
62
|
+
end
|
63
|
+
@replace_null_with_default = true
|
64
|
+
end
|
65
|
+
|
58
66
|
@owner = owner
|
59
67
|
@as = as
|
60
68
|
@loads = loads
|
@@ -97,6 +105,10 @@ module GraphQL
|
|
97
105
|
@default_value != NO_DEFAULT
|
98
106
|
end
|
99
107
|
|
108
|
+
def replace_null_with_default?
|
109
|
+
@replace_null_with_default
|
110
|
+
end
|
111
|
+
|
100
112
|
attr_writer :description
|
101
113
|
|
102
114
|
# @return [String] Documentation for this argument
|
@@ -253,6 +265,11 @@ module GraphQL
|
|
253
265
|
return
|
254
266
|
end
|
255
267
|
|
268
|
+
if value.nil? && replace_null_with_default?
|
269
|
+
value = default_value
|
270
|
+
default_used = true
|
271
|
+
end
|
272
|
+
|
256
273
|
loaded_value = nil
|
257
274
|
coerced_value = context.schema.error_handler.with_error_handling(context) do
|
258
275
|
type.coerce_input(value, context)
|
@@ -377,6 +377,7 @@ module GraphQL
|
|
377
377
|
Class.new(GraphQL::Schema::Directive) do
|
378
378
|
graphql_name(directive_definition.name)
|
379
379
|
description(directive_definition.description)
|
380
|
+
repeatable(directive_definition.repeatable)
|
380
381
|
locations(*directive_definition.locations.map { |location| location.name.to_sym })
|
381
382
|
ast_node(directive_definition)
|
382
383
|
builder.build_arguments(self, directive_definition.arguments, type_resolver)
|
@@ -90,6 +90,11 @@ module GraphQL
|
|
90
90
|
yield
|
91
91
|
end
|
92
92
|
|
93
|
+
# Continuing is passed as a block, yield to continue.
|
94
|
+
def resolve_each(object, arguments, context)
|
95
|
+
yield
|
96
|
+
end
|
97
|
+
|
93
98
|
def on_field?
|
94
99
|
locations.include?(FIELD)
|
95
100
|
end
|
@@ -101,6 +106,14 @@ module GraphQL
|
|
101
106
|
def on_operation?
|
102
107
|
locations.include?(QUERY) && locations.include?(MUTATION) && locations.include?(SUBSCRIPTION)
|
103
108
|
end
|
109
|
+
|
110
|
+
def repeatable?
|
111
|
+
!!@repeatable
|
112
|
+
end
|
113
|
+
|
114
|
+
def repeatable(new_value)
|
115
|
+
@repeatable = new_value
|
116
|
+
end
|
104
117
|
end
|
105
118
|
|
106
119
|
# @return [GraphQL::Schema::Field, GraphQL::Schema::Argument, Class, Module]
|
@@ -139,6 +152,7 @@ module GraphQL
|
|
139
152
|
ENUM_VALUE = :ENUM_VALUE,
|
140
153
|
INPUT_OBJECT = :INPUT_OBJECT,
|
141
154
|
INPUT_FIELD_DEFINITION = :INPUT_FIELD_DEFINITION,
|
155
|
+
VARIABLE_DEFINITION = :VARIABLE_DEFINITION,
|
142
156
|
]
|
143
157
|
|
144
158
|
DEFAULT_DEPRECATION_REASON = 'No longer supported'
|
@@ -161,6 +175,7 @@ module GraphQL
|
|
161
175
|
ENUM_VALUE: 'Location adjacent to an enum value definition.',
|
162
176
|
INPUT_OBJECT: 'Location adjacent to an input object type definition.',
|
163
177
|
INPUT_FIELD_DEFINITION: 'Location adjacent to an input object field definition.',
|
178
|
+
VARIABLE_DEFINITION: 'Location adjacent to a variable definition.',
|
164
179
|
}
|
165
180
|
|
166
181
|
private
|
data/lib/graphql/schema/field.rb
CHANGED
@@ -38,7 +38,9 @@ module GraphQL
|
|
38
38
|
|
39
39
|
# @return [Class] The GraphQL type this field belongs to. (For fields defined on mutations, it's the payload type)
|
40
40
|
def owner_type
|
41
|
-
@owner_type ||= if owner
|
41
|
+
@owner_type ||= if owner.nil?
|
42
|
+
raise GraphQL::InvariantError, "Field #{original_name.inspect} (graphql name: #{graphql_name.inspect}) has no owner, but all fields should have an owner. How did this happen?!"
|
43
|
+
elsif owner < GraphQL::Schema::Mutation
|
42
44
|
owner.payload_type
|
43
45
|
else
|
44
46
|
owner
|
@@ -188,6 +190,7 @@ module GraphQL
|
|
188
190
|
# @param deprecation_reason [String] If present, the field is marked "deprecated" with this message
|
189
191
|
# @param method [Symbol] The method to call on the underlying object to resolve this field (defaults to `name`)
|
190
192
|
# @param hash_key [String, Symbol] The hash key to lookup on the underlying object (if its a Hash) to resolve this field (defaults to `name` or `name.to_s`)
|
193
|
+
# @param dig [Array<String, Symbol>] The nested hash keys to lookup on the underlying hash to resolve this field using dig
|
191
194
|
# @param resolver_method [Symbol] The method on the type to call to resolve this field (defaults to `name`)
|
192
195
|
# @param connection [Boolean] `true` if this field should get automagic connection behavior; default is to infer by `*Connection` in the return type name
|
193
196
|
# @param connection_extension [Class] The extension to add, to implement connections. If `nil`, no extension is added.
|
@@ -210,7 +213,7 @@ module GraphQL
|
|
210
213
|
# @param method_conflict_warning [Boolean] If false, skip the warning if this field's method conflicts with a built-in method
|
211
214
|
# @param validates [Array<Hash>] Configurations for validating this field
|
212
215
|
# @param legacy_edge_class [Class, nil] (DEPRECATED) If present, pass this along to the legacy field definition
|
213
|
-
def initialize(type: nil, name: nil, owner: nil, null: true, field: nil, function: nil, description: nil, deprecation_reason: nil, method: nil, hash_key: nil, resolver_method: nil, resolve: nil, connection: nil, max_page_size: :not_given, scope: nil, introspection: false, camelize: true, trace: nil, complexity: 1, 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, legacy_edge_class: nil, &definition_block)
|
216
|
+
def initialize(type: nil, name: nil, owner: nil, null: true, field: nil, function: nil, description: nil, deprecation_reason: nil, method: nil, hash_key: nil, dig: nil, resolver_method: nil, resolve: nil, connection: nil, max_page_size: :not_given, scope: nil, introspection: false, camelize: true, trace: nil, complexity: 1, 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, legacy_edge_class: nil, &definition_block)
|
214
217
|
if name.nil?
|
215
218
|
raise ArgumentError, "missing first `name` argument or keyword `name:`"
|
216
219
|
end
|
@@ -236,8 +239,8 @@ module GraphQL
|
|
236
239
|
@resolve = resolve
|
237
240
|
self.deprecation_reason = deprecation_reason
|
238
241
|
|
239
|
-
if method && hash_key
|
240
|
-
raise ArgumentError, "Provide `method:` _or_ `
|
242
|
+
if method && hash_key && dig
|
243
|
+
raise ArgumentError, "Provide `method:`, `hash_key:` _or_ `dig:`, not multiple. (called with: `method: #{method.inspect}, hash_key: #{hash_key.inspect}, dig: #{dig.inspect}`)"
|
241
244
|
end
|
242
245
|
|
243
246
|
if resolver_method
|
@@ -245,13 +248,14 @@ module GraphQL
|
|
245
248
|
raise ArgumentError, "Provide `method:` _or_ `resolver_method:`, not both. (called with: `method: #{method.inspect}, resolver_method: #{resolver_method.inspect}`)"
|
246
249
|
end
|
247
250
|
|
248
|
-
if hash_key
|
249
|
-
raise ArgumentError, "Provide `hash_key
|
251
|
+
if hash_key || dig
|
252
|
+
raise ArgumentError, "Provide `hash_key:`, `dig:`, _or_ `resolver_method:`, not multiple. (called with: `hash_key: #{hash_key.inspect}, dig: #{dig.inspect}, resolver_method: #{resolver_method.inspect}`)"
|
250
253
|
end
|
251
254
|
end
|
252
255
|
|
253
256
|
# TODO: I think non-string/symbol hash keys are wrongly normalized (eg `1` will not work)
|
254
257
|
method_name = method || hash_key || name_s
|
258
|
+
@dig_keys = dig
|
255
259
|
resolver_method ||= name_s.to_sym
|
256
260
|
|
257
261
|
@method_str = -method_name.to_s
|
@@ -822,7 +826,9 @@ module GraphQL
|
|
822
826
|
end
|
823
827
|
elsif obj.object.is_a?(Hash)
|
824
828
|
inner_object = obj.object
|
825
|
-
if
|
829
|
+
if @dig_keys
|
830
|
+
inner_object.dig(*@dig_keys)
|
831
|
+
elsif inner_object.key?(@method_sym)
|
826
832
|
inner_object[@method_sym]
|
827
833
|
else
|
828
834
|
inner_object[@method_str]
|
@@ -34,6 +34,7 @@ module GraphQL
|
|
34
34
|
Class.new(GraphQL::Schema) do
|
35
35
|
orphan_types(types.values)
|
36
36
|
directives(directives)
|
37
|
+
description(schema["description"])
|
37
38
|
|
38
39
|
def self.resolve_type(*)
|
39
40
|
raise(GraphQL::RequiredImplementationMissingError, "This schema was loaded from string, so it can't resolve types for objects")
|
@@ -141,6 +142,7 @@ module GraphQL
|
|
141
142
|
Class.new(GraphQL::Schema::Scalar) do
|
142
143
|
graphql_name(type["name"])
|
143
144
|
description(type["description"])
|
145
|
+
specified_by_url(type["specifiedByUrl"])
|
144
146
|
end
|
145
147
|
end
|
146
148
|
when "UNION"
|
@@ -160,6 +162,7 @@ module GraphQL
|
|
160
162
|
graphql_name(directive["name"])
|
161
163
|
description(directive["description"])
|
162
164
|
locations(*directive["locations"].map(&:to_sym))
|
165
|
+
repeatable(directive["isRepeatable"])
|
163
166
|
loader.build_arguments(self, directive["args"], type_resolver)
|
164
167
|
end
|
165
168
|
end
|
@@ -32,6 +32,18 @@ module GraphQL
|
|
32
32
|
GraphQL::TypeKinds::SCALAR
|
33
33
|
end
|
34
34
|
|
35
|
+
def specified_by_url(new_url = nil)
|
36
|
+
if new_url
|
37
|
+
@specified_by_url = new_url
|
38
|
+
elsif defined?(@specified_by_url)
|
39
|
+
@specified_by_url
|
40
|
+
elsif superclass.respond_to?(:specified_by_url)
|
41
|
+
superclass.specified_by_url
|
42
|
+
else
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
35
47
|
def default_scalar(is_default = nil)
|
36
48
|
if !is_default.nil?
|
37
49
|
@default_scalar = is_default
|
data/lib/graphql/schema.rb
CHANGED
@@ -892,6 +892,17 @@ module GraphQL
|
|
892
892
|
GraphQL::Language::DocumentFromSchemaDefinition.new(self).document
|
893
893
|
end
|
894
894
|
|
895
|
+
# @return [String, nil]
|
896
|
+
def description(new_description = nil)
|
897
|
+
if new_description
|
898
|
+
@description = new_description
|
899
|
+
elsif defined?(@description)
|
900
|
+
@description
|
901
|
+
else
|
902
|
+
find_inherited_value(:description, nil)
|
903
|
+
end
|
904
|
+
end
|
905
|
+
|
895
906
|
def find(path)
|
896
907
|
if !@finder
|
897
908
|
@find_cache = {}
|
@@ -1247,11 +1258,7 @@ module GraphQL
|
|
1247
1258
|
when Module
|
1248
1259
|
type_or_name
|
1249
1260
|
else
|
1250
|
-
raise
|
1251
|
-
Invariant: unexpected field owner for #{field_name.inspect}: #{type_or_name.inspect} (#{type_or_name.class})
|
1252
|
-
|
1253
|
-
This is probably a bug in GraphQL-Ruby, please report this error on GitHub: https://github.com/rmosolgo/graphql-ruby/issues/new?template=bug_report.md
|
1254
|
-
ERR
|
1261
|
+
raise GraphQL::InvariantError, "Unexpected field owner for #{field_name.inspect}: #{type_or_name.inspect} (#{type_or_name.class})"
|
1255
1262
|
end
|
1256
1263
|
|
1257
1264
|
if parent_type.kind.fields? && (field = parent_type.get_field(field_name, context))
|
@@ -110,7 +110,7 @@ module GraphQL
|
|
110
110
|
end
|
111
111
|
|
112
112
|
def on_directive(node, parent)
|
113
|
-
directive_defn = @
|
113
|
+
directive_defn = @context.schema_directives[node.name]
|
114
114
|
@directive_definitions.push(directive_defn)
|
115
115
|
super
|
116
116
|
@directive_definitions.pop
|
@@ -40,7 +40,7 @@ module GraphQL
|
|
40
40
|
nodes: [used_directives[directive_name], ast_directive],
|
41
41
|
directive: directive_name,
|
42
42
|
))
|
43
|
-
|
43
|
+
elsif !((dir_defn = context.schema_directives[directive_name]) && dir_defn.repeatable?)
|
44
44
|
used_directives[directive_name] = ast_directive
|
45
45
|
end
|
46
46
|
end
|
@@ -11,7 +11,7 @@ module GraphQL
|
|
11
11
|
module ActiveSupportNotificationsTracing
|
12
12
|
# A cache of frequently-used keys to avoid needless string allocations
|
13
13
|
KEYS = NotificationsTracing::KEYS
|
14
|
-
NOTIFICATIONS_ENGINE = NotificationsTracing.new(ActiveSupport::Notifications) if defined?(ActiveSupport)
|
14
|
+
NOTIFICATIONS_ENGINE = NotificationsTracing.new(ActiveSupport::Notifications) if defined?(ActiveSupport::Notifications)
|
15
15
|
|
16
16
|
def self.trace(key, metadata, &blk)
|
17
17
|
NOTIFICATIONS_ENGINE.trace(key, metadata, &blk)
|
@@ -20,7 +20,12 @@ module GraphQL
|
|
20
20
|
|
21
21
|
if key == 'execute_multiplex'
|
22
22
|
operations = data[:multiplex].queries.map(&:selected_operation_name).join(', ')
|
23
|
-
span.resource =
|
23
|
+
span.resource = if operations.empty?
|
24
|
+
first_query = data[:multiplex].queries.first
|
25
|
+
fallback_transaction_name(first_query && first_query.context)
|
26
|
+
else
|
27
|
+
operations
|
28
|
+
end
|
24
29
|
|
25
30
|
# For top span of query, set the analytics sample rate tag, if available.
|
26
31
|
if analytics_enabled?
|
@@ -104,17 +104,22 @@ module GraphQL
|
|
104
104
|
|
105
105
|
private
|
106
106
|
|
107
|
-
# Get the transaction name based on the operation type and name
|
107
|
+
# Get the transaction name based on the operation type and name if possible, or fall back to a user provided
|
108
|
+
# one. Useful for anonymous queries.
|
108
109
|
def transaction_name(query)
|
109
110
|
selected_op = query.selected_operation
|
110
|
-
if selected_op
|
111
|
+
txn_name = if selected_op
|
111
112
|
op_type = selected_op.operation_type
|
112
|
-
op_name = selected_op.name || "anonymous"
|
113
|
+
op_name = selected_op.name || fallback_transaction_name(query.context) || "anonymous"
|
114
|
+
"#{op_type}.#{op_name}"
|
113
115
|
else
|
114
|
-
|
115
|
-
op_name = "anonymous"
|
116
|
+
"query.anonymous"
|
116
117
|
end
|
117
|
-
"GraphQL/#{
|
118
|
+
"GraphQL/#{txn_name}"
|
119
|
+
end
|
120
|
+
|
121
|
+
def fallback_transaction_name(context)
|
122
|
+
context[:tracing_fallback_transaction_name]
|
118
123
|
end
|
119
124
|
|
120
125
|
attr_reader :options
|
@@ -21,13 +21,21 @@ module GraphQL
|
|
21
21
|
Date.parse(value.to_s).iso8601
|
22
22
|
end
|
23
23
|
|
24
|
-
# @param str_value [String]
|
24
|
+
# @param str_value [String, Date, DateTime, Time]
|
25
25
|
# @return [Date]
|
26
|
-
def self.coerce_input(
|
27
|
-
|
26
|
+
def self.coerce_input(value, ctx)
|
27
|
+
if value.is_a?(::Date)
|
28
|
+
value
|
29
|
+
elsif value.is_a?(::DateTime)
|
30
|
+
value.to_date
|
31
|
+
elsif value.is_a?(::Time)
|
32
|
+
value.to_date
|
33
|
+
else
|
34
|
+
Date.iso8601(value)
|
35
|
+
end
|
28
36
|
rescue ArgumentError, TypeError
|
29
|
-
|
30
|
-
|
37
|
+
err = GraphQL::DateEncodingError.new(value)
|
38
|
+
ctx.schema.type_error(err, ctx)
|
31
39
|
end
|
32
40
|
end
|
33
41
|
end
|
@@ -54,7 +54,14 @@ module GraphQL
|
|
54
54
|
Time.iso8601(str_value)
|
55
55
|
rescue ArgumentError, TypeError
|
56
56
|
begin
|
57
|
-
Date.iso8601(str_value).to_time
|
57
|
+
dt = Date.iso8601(str_value).to_time
|
58
|
+
# For compatibility, continue accepting dates given without times
|
59
|
+
# But without this, it would zero out given any time part of `str_value` (hours and/or minutes)
|
60
|
+
if dt.iso8601.start_with?(str_value)
|
61
|
+
dt
|
62
|
+
else
|
63
|
+
nil
|
64
|
+
end
|
58
65
|
rescue ArgumentError, TypeError
|
59
66
|
# Invalid input
|
60
67
|
nil
|
@@ -83,7 +83,8 @@ module GraphQL
|
|
83
83
|
end
|
84
84
|
|
85
85
|
def visible?(ctx)
|
86
|
-
node_type
|
86
|
+
# if this is an abstract base class, there may be no `node_type`
|
87
|
+
node_type ? node_type.visible?(ctx) : super
|
87
88
|
end
|
88
89
|
|
89
90
|
# Set the default `node_nullable` for this class and its child classes. (Defaults to `true`.)
|
@@ -18,18 +18,6 @@ module GraphQL
|
|
18
18
|
# context.schema.object_from_id(id, context)
|
19
19
|
# end
|
20
20
|
#
|
21
|
-
def self.const_missing(const_name)
|
22
|
-
if const_name == :NodeField
|
23
|
-
message = "NodeField is deprecated, use `include GraphQL::Types::Relay::HasNodeField` instead."
|
24
|
-
message += "\n(referenced from #{caller(1, 1).first})"
|
25
|
-
GraphQL::Deprecation.warn(message)
|
26
|
-
|
27
|
-
DeprecatedNodeField
|
28
|
-
else
|
29
|
-
super
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
21
|
DeprecatedNodeField = GraphQL::Schema::Field.new(owner: nil, **HasNodeField.field_options, &HasNodeField.field_block)
|
34
22
|
end
|
35
23
|
end
|
@@ -27,6 +27,12 @@ module GraphQL
|
|
27
27
|
GraphQL::Deprecation.warn(message)
|
28
28
|
|
29
29
|
DeprecatedNodesField
|
30
|
+
elsif const_name == :NodeField
|
31
|
+
message = "NodeField is deprecated, use `include GraphQL::Types::Relay::HasNodeField` instead."
|
32
|
+
message += "\n(referenced from #{caller(1, 1).first})"
|
33
|
+
GraphQL::Deprecation.warn(message)
|
34
|
+
|
35
|
+
DeprecatedNodeField
|
30
36
|
else
|
31
37
|
super
|
32
38
|
end
|
data/lib/graphql/version.rb
CHANGED
data/lib/graphql.rb
CHANGED
@@ -17,6 +17,17 @@ module GraphQL
|
|
17
17
|
class Error < StandardError
|
18
18
|
end
|
19
19
|
|
20
|
+
# This error is raised when GraphQL-Ruby encounters a situation
|
21
|
+
# that it *thought* would never happen. Please report this bug!
|
22
|
+
class InvariantError < Error
|
23
|
+
def initialize(message)
|
24
|
+
message += "
|
25
|
+
|
26
|
+
This is probably a bug in GraphQL-Ruby, please report this error on GitHub: https://github.com/rmosolgo/graphql-ruby/issues/new?template=bug_report.md"
|
27
|
+
super(message)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
20
31
|
class RequiredImplementationMissingError < Error
|
21
32
|
end
|
22
33
|
|
@@ -69,6 +80,7 @@ require "graphql/invalid_name_error"
|
|
69
80
|
require "graphql/integer_decoding_error"
|
70
81
|
require "graphql/integer_encoding_error"
|
71
82
|
require "graphql/string_encoding_error"
|
83
|
+
require "graphql/date_encoding_error"
|
72
84
|
|
73
85
|
require "graphql/define"
|
74
86
|
require "graphql/base_type"
|