graphql 1.13.3 → 1.13.7
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 +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"
|