graphql 1.11.6 → 1.13.19
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 +3 -8
- 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/install_generator.rb +17 -7
- data/lib/generators/graphql/interface_generator.rb +7 -7
- data/lib/generators/graphql/loader_generator.rb +1 -0
- 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 +6 -30
- data/lib/generators/graphql/mutation_update_generator.rb +22 -0
- data/lib/generators/graphql/object_generator.rb +12 -38
- data/lib/generators/graphql/orm_mutations_base.rb +40 -0
- data/lib/generators/graphql/relay.rb +63 -0
- data/lib/generators/graphql/relay_generator.rb +21 -0
- data/lib/generators/graphql/scalar_generator.rb +4 -2
- data/lib/generators/graphql/templates/base_connection.erb +8 -0
- data/lib/generators/graphql/templates/base_edge.erb +8 -0
- data/lib/generators/graphql/templates/enum.erb +5 -1
- data/lib/generators/graphql/templates/graphql_controller.erb +2 -2
- 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/node_type.erb +9 -0
- data/lib/generators/graphql/templates/object.erb +5 -3
- data/lib/generators/graphql/templates/query_type.erb +1 -3
- data/lib/generators/graphql/templates/scalar.erb +3 -1
- data/lib/generators/graphql/templates/schema.erb +19 -34
- data/lib/generators/graphql/templates/union.erb +4 -2
- data/lib/generators/graphql/type_generator.rb +47 -10
- data/lib/generators/graphql/union_generator.rb +5 -5
- data/lib/graphql/analysis/analyze_query.rb +7 -0
- data/lib/graphql/analysis/ast/field_usage.rb +28 -1
- data/lib/graphql/analysis/ast/query_complexity.rb +10 -14
- data/lib/graphql/analysis/ast/visitor.rb +14 -5
- data/lib/graphql/analysis/ast.rb +11 -2
- data/lib/graphql/argument.rb +1 -1
- data/lib/graphql/backtrace/inspect_result.rb +0 -1
- data/lib/graphql/backtrace/legacy_tracer.rb +56 -0
- data/lib/graphql/backtrace/table.rb +34 -3
- data/lib/graphql/backtrace/traced_error.rb +0 -1
- data/lib/graphql/backtrace/tracer.rb +40 -10
- data/lib/graphql/backtrace.rb +28 -19
- data/lib/graphql/backwards_compatibility.rb +2 -1
- data/lib/graphql/base_type.rb +6 -4
- data/lib/graphql/boolean_type.rb +1 -1
- data/lib/graphql/compatibility/execution_specification.rb +1 -0
- data/lib/graphql/compatibility/lazy_execution_specification.rb +2 -0
- data/lib/graphql/compatibility/query_parser_specification.rb +2 -0
- data/lib/graphql/compatibility/schema_parser_specification.rb +2 -0
- data/lib/graphql/dataloader/null_dataloader.rb +22 -0
- data/lib/graphql/dataloader/request.rb +19 -0
- data/lib/graphql/dataloader/request_all.rb +19 -0
- data/lib/graphql/dataloader/source.rb +155 -0
- data/lib/graphql/dataloader.rb +308 -0
- data/lib/graphql/date_encoding_error.rb +16 -0
- data/lib/graphql/define/assign_global_id_field.rb +1 -1
- data/lib/graphql/define/instance_definable.rb +48 -3
- data/lib/graphql/define/type_definer.rb +5 -5
- data/lib/graphql/deprecated_dsl.rb +18 -5
- data/lib/graphql/deprecation.rb +9 -0
- data/lib/graphql/directive/deprecated_directive.rb +1 -1
- data/lib/graphql/directive/include_directive.rb +1 -1
- data/lib/graphql/directive/skip_directive.rb +1 -1
- data/lib/graphql/directive.rb +1 -5
- data/lib/graphql/enum_type.rb +9 -3
- data/lib/graphql/execution/errors.rb +110 -7
- data/lib/graphql/execution/execute.rb +8 -1
- data/lib/graphql/execution/interpreter/arguments.rb +57 -5
- data/lib/graphql/execution/interpreter/arguments_cache.rb +49 -15
- data/lib/graphql/execution/interpreter/handles_raw_value.rb +0 -7
- data/lib/graphql/execution/interpreter/resolve.rb +37 -25
- data/lib/graphql/execution/interpreter/runtime.rb +670 -294
- data/lib/graphql/execution/interpreter.rb +16 -16
- data/lib/graphql/execution/lazy.rb +5 -1
- data/lib/graphql/execution/lookahead.rb +2 -2
- data/lib/graphql/execution/multiplex.rb +39 -23
- data/lib/graphql/field.rb +1 -1
- data/lib/graphql/float_type.rb +1 -1
- data/lib/graphql/function.rb +4 -0
- data/lib/graphql/id_type.rb +1 -1
- data/lib/graphql/input_object_type.rb +3 -1
- data/lib/graphql/int_type.rb +1 -1
- data/lib/graphql/integer_decoding_error.rb +17 -0
- data/lib/graphql/integer_encoding_error.rb +18 -2
- data/lib/graphql/interface_type.rb +4 -2
- data/lib/graphql/internal_representation/document.rb +2 -2
- data/lib/graphql/internal_representation/rewrite.rb +1 -1
- data/lib/graphql/introspection/directive_location_enum.rb +2 -2
- data/lib/graphql/introspection/directive_type.rb +11 -5
- data/lib/graphql/introspection/entry_points.rb +2 -2
- data/lib/graphql/introspection/enum_value_type.rb +2 -2
- data/lib/graphql/introspection/field_type.rb +3 -3
- data/lib/graphql/introspection/input_value_type.rb +10 -4
- data/lib/graphql/introspection/schema_type.rb +10 -5
- data/lib/graphql/introspection/type_type.rb +18 -12
- data/lib/graphql/introspection.rb +5 -2
- data/lib/graphql/invalid_null_error.rb +1 -1
- data/lib/graphql/language/block_string.rb +2 -6
- data/lib/graphql/language/cache.rb +37 -0
- data/lib/graphql/language/document_from_schema_definition.rb +60 -26
- data/lib/graphql/language/lexer.rb +50 -28
- data/lib/graphql/language/lexer.rl +2 -4
- data/lib/graphql/language/nodes.rb +14 -4
- data/lib/graphql/language/parser.rb +856 -825
- data/lib/graphql/language/parser.y +28 -11
- data/lib/graphql/language/printer.rb +10 -1
- data/lib/graphql/language/sanitized_printer.rb +5 -5
- data/lib/graphql/language/token.rb +0 -4
- data/lib/graphql/language.rb +1 -0
- data/lib/graphql/name_validator.rb +0 -4
- data/lib/graphql/object_type.rb +4 -4
- data/lib/graphql/pagination/active_record_relation_connection.rb +47 -3
- data/lib/graphql/pagination/connection.rb +19 -1
- data/lib/graphql/pagination/connections.rb +45 -30
- data/lib/graphql/pagination/relation_connection.rb +69 -28
- data/lib/graphql/parse_error.rb +0 -1
- data/lib/graphql/query/arguments.rb +2 -2
- data/lib/graphql/query/arguments_cache.rb +1 -2
- data/lib/graphql/query/context.rb +22 -4
- data/lib/graphql/query/executor.rb +0 -1
- data/lib/graphql/query/input_validation_result.rb +9 -0
- data/lib/graphql/query/literal_input.rb +1 -1
- data/lib/graphql/query/null_context.rb +21 -9
- data/lib/graphql/query/serial_execution/field_resolution.rb +1 -1
- data/lib/graphql/query/serial_execution.rb +1 -0
- data/lib/graphql/query/validation_pipeline.rb +3 -4
- data/lib/graphql/query/variable_validation_error.rb +3 -3
- data/lib/graphql/query/variables.rb +35 -4
- data/lib/graphql/query.rb +20 -8
- data/lib/graphql/railtie.rb +9 -1
- data/lib/graphql/rake_task.rb +3 -0
- data/lib/graphql/relay/array_connection.rb +2 -2
- data/lib/graphql/relay/base_connection.rb +7 -0
- data/lib/graphql/relay/connection_instrumentation.rb +4 -4
- data/lib/graphql/relay/connection_type.rb +16 -3
- data/lib/graphql/relay/edges_instrumentation.rb +0 -1
- data/lib/graphql/relay/global_id_resolve.rb +1 -2
- data/lib/graphql/relay/mutation.rb +2 -1
- data/lib/graphql/relay/node.rb +3 -0
- data/lib/graphql/relay/page_info.rb +1 -1
- data/lib/graphql/relay/range_add.rb +14 -5
- data/lib/graphql/relay/type_extensions.rb +2 -0
- data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
- data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
- data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
- data/lib/graphql/rubocop.rb +4 -0
- data/lib/graphql/scalar_type.rb +3 -1
- data/lib/graphql/schema/addition.rb +247 -0
- data/lib/graphql/schema/argument.rb +177 -21
- data/lib/graphql/schema/build_from_definition.rb +150 -55
- data/lib/graphql/schema/default_type_error.rb +2 -0
- data/lib/graphql/schema/directive/feature.rb +1 -1
- data/lib/graphql/schema/directive/flagged.rb +57 -0
- data/lib/graphql/schema/directive/include.rb +1 -1
- data/lib/graphql/schema/directive/skip.rb +1 -1
- data/lib/graphql/schema/directive/transform.rb +14 -2
- data/lib/graphql/schema/directive.rb +103 -4
- data/lib/graphql/schema/enum.rb +72 -11
- data/lib/graphql/schema/enum_value.rb +18 -6
- data/lib/graphql/schema/field/connection_extension.rb +4 -2
- data/lib/graphql/schema/field/scope_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +332 -111
- data/lib/graphql/schema/field_extension.rb +89 -2
- data/lib/graphql/schema/find_inherited_value.rb +4 -1
- data/lib/graphql/schema/finder.rb +5 -5
- data/lib/graphql/schema/input_object.rb +79 -55
- data/lib/graphql/schema/interface.rb +12 -20
- data/lib/graphql/schema/introspection_system.rb +1 -1
- data/lib/graphql/schema/list.rb +21 -4
- data/lib/graphql/schema/loader.rb +11 -0
- data/lib/graphql/schema/member/accepts_definition.rb +15 -3
- data/lib/graphql/schema/member/base_dsl_methods.rb +5 -16
- data/lib/graphql/schema/member/build_type.rb +4 -7
- data/lib/graphql/schema/member/cached_graphql_definition.rb +29 -2
- data/lib/graphql/schema/member/has_arguments.rb +166 -74
- data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
- data/lib/graphql/schema/member/has_directives.rb +98 -0
- data/lib/graphql/schema/member/has_fields.rb +77 -22
- data/lib/graphql/schema/member/has_interfaces.rb +100 -0
- data/lib/graphql/schema/member/has_validators.rb +31 -0
- data/lib/graphql/schema/member/instrumentation.rb +0 -1
- data/lib/graphql/schema/member/type_system_helpers.rb +1 -1
- data/lib/graphql/schema/member/validates_input.rb +2 -2
- data/lib/graphql/schema/member.rb +5 -0
- data/lib/graphql/schema/middleware_chain.rb +1 -1
- data/lib/graphql/schema/non_null.rb +9 -3
- data/lib/graphql/schema/object.rb +40 -80
- data/lib/graphql/schema/printer.rb +16 -20
- data/lib/graphql/schema/relay_classic_mutation.rb +38 -4
- data/lib/graphql/schema/resolver/has_payload_type.rb +29 -2
- data/lib/graphql/schema/resolver.rb +110 -64
- data/lib/graphql/schema/scalar.rb +18 -2
- data/lib/graphql/schema/subscription.rb +55 -9
- data/lib/graphql/schema/timeout_middleware.rb +3 -1
- data/lib/graphql/schema/traversal.rb +1 -1
- data/lib/graphql/schema/type_expression.rb +1 -1
- data/lib/graphql/schema/type_membership.rb +18 -4
- data/lib/graphql/schema/union.rb +8 -1
- data/lib/graphql/schema/validation.rb +4 -2
- data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
- data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
- data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
- data/lib/graphql/schema/validator/format_validator.rb +48 -0
- data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
- data/lib/graphql/schema/validator/length_validator.rb +59 -0
- data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
- data/lib/graphql/schema/validator/required_validator.rb +82 -0
- data/lib/graphql/schema/validator.rb +171 -0
- data/lib/graphql/schema/warden.rb +126 -53
- data/lib/graphql/schema.rb +262 -281
- data/lib/graphql/static_validation/all_rules.rb +2 -0
- data/lib/graphql/static_validation/base_visitor.rb +9 -6
- data/lib/graphql/static_validation/definition_dependencies.rb +0 -1
- data/lib/graphql/static_validation/error.rb +3 -1
- data/lib/graphql/static_validation/literal_validator.rb +1 -1
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +4 -2
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +6 -2
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +3 -2
- data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
- data/lib/graphql/static_validation/rules/directives_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/fields_will_merge.rb +90 -47
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
- data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
- data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
- data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
- data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -2
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +5 -5
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +14 -8
- data/lib/graphql/static_validation/validation_context.rb +12 -2
- data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
- data/lib/graphql/static_validation/validator.rb +41 -10
- data/lib/graphql/static_validation.rb +1 -0
- data/lib/graphql/string_encoding_error.rb +13 -3
- data/lib/graphql/string_type.rb +1 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +39 -8
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +0 -3
- data/lib/graphql/subscriptions/event.rb +68 -32
- data/lib/graphql/subscriptions/instrumentation.rb +0 -1
- data/lib/graphql/subscriptions/serialize.rb +34 -5
- data/lib/graphql/subscriptions/subscription_root.rb +1 -1
- data/lib/graphql/subscriptions.rb +34 -39
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +8 -21
- data/lib/graphql/tracing/appoptics_tracing.rb +3 -1
- data/lib/graphql/tracing/appsignal_tracing.rb +15 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +24 -2
- data/lib/graphql/tracing/notifications_tracing.rb +59 -0
- data/lib/graphql/tracing/platform_tracing.rb +24 -12
- data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
- data/lib/graphql/tracing/skylight_tracing.rb +1 -1
- data/lib/graphql/tracing.rb +2 -2
- data/lib/graphql/types/big_int.rb +5 -1
- data/lib/graphql/types/int.rb +10 -3
- 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/base_connection.rb +6 -91
- data/lib/graphql/types/relay/base_edge.rb +2 -34
- data/lib/graphql/types/relay/connection_behaviors.rb +174 -0
- data/lib/graphql/types/relay/default_relay.rb +31 -0
- data/lib/graphql/types/relay/edge_behaviors.rb +64 -0
- data/lib/graphql/types/relay/has_node_field.rb +41 -0
- data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
- data/lib/graphql/types/relay/node.rb +2 -4
- data/lib/graphql/types/relay/node_behaviors.rb +15 -0
- data/lib/graphql/types/relay/node_field.rb +3 -22
- data/lib/graphql/types/relay/nodes_field.rb +16 -18
- data/lib/graphql/types/relay/page_info.rb +2 -14
- data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
- data/lib/graphql/types/relay.rb +11 -3
- data/lib/graphql/types/string.rb +8 -2
- data/lib/graphql/unauthorized_error.rb +1 -1
- data/lib/graphql/union_type.rb +3 -1
- data/lib/graphql/upgrader/member.rb +1 -0
- data/lib/graphql/upgrader/schema.rb +1 -0
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +68 -37
- data/readme.md +3 -6
- metadata +83 -113
- data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
- data/lib/graphql/types/relay/base_field.rb +0 -22
- data/lib/graphql/types/relay/base_interface.rb +0 -29
- data/lib/graphql/types/relay/base_object.rb +0 -26
- /data/lib/generators/graphql/{templates → install/templates}/base_mutation.erb +0 -0
- /data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +0 -0
@@ -16,6 +16,13 @@ module GraphQL
|
|
16
16
|
class InvalidTriggerError < GraphQL::Error
|
17
17
|
end
|
18
18
|
|
19
|
+
# Raised when either:
|
20
|
+
# - An initial subscription didn't have a value for `context[subscription_scope]`
|
21
|
+
# - Or, an update didn't pass `.trigger(..., scope:)`
|
22
|
+
# When raised, the initial subscription or update fails completely.
|
23
|
+
class SubscriptionScopeMissingError < GraphQL::Error
|
24
|
+
end
|
25
|
+
|
19
26
|
# @see {Subscriptions#initialize} for options, concrete implementations may add options.
|
20
27
|
def self.use(defn, options = {})
|
21
28
|
schema = defn.is_a?(Class) ? defn : defn.target
|
@@ -26,7 +33,9 @@ module GraphQL
|
|
26
33
|
|
27
34
|
instrumentation = Subscriptions::Instrumentation.new(schema: schema)
|
28
35
|
defn.instrument(:query, instrumentation)
|
29
|
-
|
36
|
+
if !schema.is_a?(Class)
|
37
|
+
defn.instrument(:field, instrumentation)
|
38
|
+
end
|
30
39
|
options[:schema] = schema
|
31
40
|
schema.subscriptions = self.new(**options)
|
32
41
|
schema.add_subscription_extension_if_necessary
|
@@ -74,7 +83,8 @@ module GraphQL
|
|
74
83
|
end
|
75
84
|
|
76
85
|
# Normalize symbol-keyed args to strings, try camelizing them
|
77
|
-
|
86
|
+
# Should this accept a real context somehow?
|
87
|
+
normalized_args = normalize_arguments(normalized_event_name, field, args, GraphQL::Query::NullContext)
|
78
88
|
|
79
89
|
event = Subscriptions::Event.new(
|
80
90
|
name: normalized_event_name,
|
@@ -107,31 +117,26 @@ module GraphQL
|
|
107
117
|
variables = query_data.fetch(:variables)
|
108
118
|
context = query_data.fetch(:context)
|
109
119
|
operation_name = query_data.fetch(:operation_name)
|
110
|
-
result =
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
context: context,
|
122
|
-
subscription_topic: event.topic,
|
123
|
-
operation_name: operation_name,
|
124
|
-
variables: variables,
|
125
|
-
root_value: object,
|
126
|
-
)
|
127
|
-
end
|
128
|
-
unsubscribed = false
|
120
|
+
result = @schema.execute(
|
121
|
+
query: query_string,
|
122
|
+
context: context,
|
123
|
+
subscription_topic: event.topic,
|
124
|
+
operation_name: operation_name,
|
125
|
+
variables: variables,
|
126
|
+
root_value: object,
|
127
|
+
)
|
128
|
+
subscriptions_context = result.context.namespace(:subscriptions)
|
129
|
+
if subscriptions_context[:no_update]
|
130
|
+
result = nil
|
129
131
|
end
|
130
132
|
|
133
|
+
unsubscribed = subscriptions_context[:unsubscribed]
|
134
|
+
|
131
135
|
if unsubscribed
|
132
136
|
# `unsubscribe` was called, clean up on our side
|
133
137
|
# TODO also send `{more: false}` to client?
|
134
138
|
delete_subscription(subscription_id)
|
139
|
+
result = nil
|
135
140
|
end
|
136
141
|
|
137
142
|
result
|
@@ -154,16 +159,6 @@ module GraphQL
|
|
154
159
|
# @param object [Object]
|
155
160
|
# @return [void]
|
156
161
|
def execute_all(event, object)
|
157
|
-
each_subscription_id(event) do |subscription_id|
|
158
|
-
execute(subscription_id, event, object)
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
# Get each `subscription_id` subscribed to `event.topic` and yield them
|
163
|
-
# @param event [GraphQL::Subscriptions::Event]
|
164
|
-
# @yieldparam subscription_id [String]
|
165
|
-
# @return [void]
|
166
|
-
def each_subscription_id(event)
|
167
162
|
raise GraphQL::RequiredImplementationMissingError
|
168
163
|
end
|
169
164
|
|
@@ -236,7 +231,7 @@ module GraphQL
|
|
236
231
|
# @param arg_owner [GraphQL::Field, GraphQL::BaseType]
|
237
232
|
# @param args [Hash, Array, Any] some GraphQL input value to coerce as `arg_owner`
|
238
233
|
# @return [Any] normalized arguments value
|
239
|
-
def normalize_arguments(event_name, arg_owner, args)
|
234
|
+
def normalize_arguments(event_name, arg_owner, args, context)
|
240
235
|
case arg_owner
|
241
236
|
when GraphQL::Field, GraphQL::InputObjectType, GraphQL::Schema::Field, Class
|
242
237
|
if arg_owner.is_a?(Class) && !arg_owner.kind.input_object?
|
@@ -247,19 +242,19 @@ module GraphQL
|
|
247
242
|
missing_arg_names = []
|
248
243
|
args.each do |k, v|
|
249
244
|
arg_name = k.to_s
|
250
|
-
arg_defn = arg_owner.
|
245
|
+
arg_defn = arg_owner.get_argument(arg_name, context)
|
251
246
|
if arg_defn
|
252
247
|
normalized_arg_name = arg_name
|
253
248
|
else
|
254
249
|
normalized_arg_name = normalize_name(arg_name)
|
255
|
-
arg_defn = arg_owner.
|
250
|
+
arg_defn = arg_owner.get_argument(normalized_arg_name, context)
|
256
251
|
end
|
257
252
|
|
258
253
|
if arg_defn
|
259
254
|
if arg_defn.loads
|
260
255
|
normalized_arg_name = arg_defn.keyword.to_s
|
261
256
|
end
|
262
|
-
normalized = normalize_arguments(event_name, arg_defn.type, v)
|
257
|
+
normalized = normalize_arguments(event_name, arg_defn.type, v, context)
|
263
258
|
normalized_args[normalized_arg_name] = normalized
|
264
259
|
else
|
265
260
|
# Couldn't find a matching argument definition
|
@@ -269,12 +264,12 @@ module GraphQL
|
|
269
264
|
|
270
265
|
# Backfill default values so that trigger arguments
|
271
266
|
# match query arguments.
|
272
|
-
arg_owner.arguments.each do |
|
267
|
+
arg_owner.arguments(context).each do |_name, arg_defn|
|
273
268
|
if arg_defn.default_value? && !normalized_args.key?(arg_defn.name)
|
274
269
|
default_value = arg_defn.default_value
|
275
270
|
# We don't have an underlying "object" here, so it can't call methods.
|
276
271
|
# This is broken.
|
277
|
-
normalized_args[arg_defn.name] = arg_defn.prepare_value(nil, default_value, context:
|
272
|
+
normalized_args[arg_defn.name] = arg_defn.prepare_value(nil, default_value, context: context)
|
278
273
|
end
|
279
274
|
end
|
280
275
|
|
@@ -293,9 +288,9 @@ module GraphQL
|
|
293
288
|
|
294
289
|
normalized_args
|
295
290
|
when GraphQL::ListType, GraphQL::Schema::List
|
296
|
-
args.map { |a| normalize_arguments(event_name, arg_owner.of_type, a) }
|
291
|
+
args.map { |a| normalize_arguments(event_name, arg_owner.of_type, a, context) }
|
297
292
|
when GraphQL::NonNullType, GraphQL::Schema::NonNull
|
298
|
-
normalize_arguments(event_name, arg_owner.of_type, args)
|
293
|
+
normalize_arguments(event_name, arg_owner.of_type, args, context)
|
299
294
|
else
|
300
295
|
args
|
301
296
|
end
|
@@ -1,33 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'graphql/tracing/notifications_tracing'
|
4
|
+
|
3
5
|
module GraphQL
|
4
6
|
module Tracing
|
5
7
|
# This implementation forwards events to ActiveSupport::Notifications
|
6
|
-
# with a `graphql
|
8
|
+
# with a `graphql` suffix.
|
7
9
|
#
|
10
|
+
# @see KEYS for event names
|
8
11
|
module ActiveSupportNotificationsTracing
|
9
12
|
# A cache of frequently-used keys to avoid needless string allocations
|
10
|
-
KEYS =
|
11
|
-
|
12
|
-
"parse" => "parse.graphql",
|
13
|
-
"validate" => "validate.graphql",
|
14
|
-
"analyze_multiplex" => "analyze_multiplex.graphql",
|
15
|
-
"analyze_query" => "analyze_query.graphql",
|
16
|
-
"execute_query" => "execute_query.graphql",
|
17
|
-
"execute_query_lazy" => "execute_query_lazy.graphql",
|
18
|
-
"execute_field" => "execute_field.graphql",
|
19
|
-
"execute_field_lazy" => "execute_field_lazy.graphql",
|
20
|
-
"authorized" => "authorized.graphql",
|
21
|
-
"authorized_lazy" => "authorized_lazy.graphql",
|
22
|
-
"resolve_type" => "resolve_type.graphql",
|
23
|
-
"resolve_type_lazy" => "resolve_type.graphql",
|
24
|
-
}
|
13
|
+
KEYS = NotificationsTracing::KEYS
|
14
|
+
NOTIFICATIONS_ENGINE = NotificationsTracing.new(ActiveSupport::Notifications) if defined?(ActiveSupport::Notifications)
|
25
15
|
|
26
|
-
def self.trace(key, metadata)
|
27
|
-
|
28
|
-
ActiveSupport::Notifications.instrument(prefixed_key, metadata) do
|
29
|
-
yield
|
30
|
-
end
|
16
|
+
def self.trace(key, metadata, &blk)
|
17
|
+
NOTIFICATIONS_ENGINE.trace(key, metadata, &blk)
|
31
18
|
end
|
32
19
|
end
|
33
20
|
end
|
@@ -57,7 +57,7 @@ module GraphQL
|
|
57
57
|
def platform_field_key(type, field)
|
58
58
|
"graphql.#{type.graphql_name}.#{field.graphql_name}"
|
59
59
|
end
|
60
|
-
|
60
|
+
|
61
61
|
def platform_authorized_key(type)
|
62
62
|
"graphql.authorized.#{type.graphql_name}"
|
63
63
|
end
|
@@ -112,6 +112,8 @@ module GraphQL
|
|
112
112
|
graphql_query_string(data[key])
|
113
113
|
when :multiplex
|
114
114
|
graphql_multiplex(data[key])
|
115
|
+
when :path
|
116
|
+
[key, data[key].join(".")]
|
115
117
|
else
|
116
118
|
[key, data[key]]
|
117
119
|
end
|
@@ -14,7 +14,22 @@ module GraphQL
|
|
14
14
|
"execute_query_lazy" => "execute.graphql",
|
15
15
|
}
|
16
16
|
|
17
|
+
# @param set_action_name [Boolean] If true, the GraphQL operation name will be used as the transaction name.
|
18
|
+
# This is not advised if you run more than one query per HTTP request, for example, with `graphql-client` or multiplexing.
|
19
|
+
# It can also be specified per-query with `context[:set_appsignal_action_name]`.
|
20
|
+
def initialize(options = {})
|
21
|
+
@set_action_name = options.fetch(:set_action_name, false)
|
22
|
+
super
|
23
|
+
end
|
24
|
+
|
17
25
|
def platform_trace(platform_key, key, data)
|
26
|
+
if key == "execute_query"
|
27
|
+
set_this_txn_name = data[:query].context[:set_appsignal_action_name]
|
28
|
+
if set_this_txn_name == true || (set_this_txn_name.nil? && @set_action_name)
|
29
|
+
Appsignal::Transaction.current.set_action(transaction_name(data[:query]))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
18
33
|
Appsignal.instrument(platform_key) do
|
19
34
|
yield
|
20
35
|
end
|
@@ -17,10 +17,21 @@ module GraphQL
|
|
17
17
|
def platform_trace(platform_key, key, data)
|
18
18
|
tracer.trace(platform_key, service: service_name) do |span|
|
19
19
|
span.span_type = 'custom'
|
20
|
+
if defined?(Datadog::Tracing::Metadata::Ext) # Introduced in ddtrace 1.0
|
21
|
+
span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT, 'graphql')
|
22
|
+
span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION, key)
|
23
|
+
end
|
20
24
|
|
21
25
|
if key == 'execute_multiplex'
|
22
26
|
operations = data[:multiplex].queries.map(&:selected_operation_name).join(', ')
|
23
|
-
|
27
|
+
|
28
|
+
resource = if operations.empty?
|
29
|
+
first_query = data[:multiplex].queries.first
|
30
|
+
fallback_transaction_name(first_query && first_query.context)
|
31
|
+
else
|
32
|
+
operations
|
33
|
+
end
|
34
|
+
span.resource = resource if resource
|
24
35
|
|
25
36
|
# For top span of query, set the analytics sample rate tag, if available.
|
26
37
|
if analytics_enabled?
|
@@ -34,6 +45,8 @@ module GraphQL
|
|
34
45
|
span.set_tag(:query_string, data[:query].query_string)
|
35
46
|
end
|
36
47
|
|
48
|
+
prepare_span(key, data, span)
|
49
|
+
|
37
50
|
yield
|
38
51
|
end
|
39
52
|
end
|
@@ -42,8 +55,17 @@ module GraphQL
|
|
42
55
|
options.fetch(:service, 'ruby-graphql')
|
43
56
|
end
|
44
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
|
+
|
45
65
|
def tracer
|
46
|
-
|
66
|
+
default_tracer = defined?(Datadog::Tracing) ? Datadog::Tracing : Datadog.tracer
|
67
|
+
|
68
|
+
options.fetch(:tracer, default_tracer)
|
47
69
|
end
|
48
70
|
|
49
71
|
def analytics_available?
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Tracing
|
5
|
+
# This implementation forwards events to a notification handler (i.e.
|
6
|
+
# ActiveSupport::Notifications or Dry::Monitor::Notifications)
|
7
|
+
# with a `graphql` suffix.
|
8
|
+
#
|
9
|
+
# @see KEYS for event names
|
10
|
+
class NotificationsTracing
|
11
|
+
# A cache of frequently-used keys to avoid needless string allocations
|
12
|
+
KEYS = {
|
13
|
+
"lex" => "lex.graphql",
|
14
|
+
"parse" => "parse.graphql",
|
15
|
+
"validate" => "validate.graphql",
|
16
|
+
"analyze_multiplex" => "analyze_multiplex.graphql",
|
17
|
+
"analyze_query" => "analyze_query.graphql",
|
18
|
+
"execute_query" => "execute_query.graphql",
|
19
|
+
"execute_query_lazy" => "execute_query_lazy.graphql",
|
20
|
+
"execute_field" => "execute_field.graphql",
|
21
|
+
"execute_field_lazy" => "execute_field_lazy.graphql",
|
22
|
+
"authorized" => "authorized.graphql",
|
23
|
+
"authorized_lazy" => "authorized_lazy.graphql",
|
24
|
+
"resolve_type" => "resolve_type.graphql",
|
25
|
+
"resolve_type_lazy" => "resolve_type.graphql",
|
26
|
+
}
|
27
|
+
|
28
|
+
MAX_KEYS_SIZE = 100
|
29
|
+
|
30
|
+
# Initialize a new NotificationsTracing instance
|
31
|
+
#
|
32
|
+
# @param [Object] notifications_engine The notifications engine to use
|
33
|
+
def initialize(notifications_engine)
|
34
|
+
@notifications_engine = notifications_engine
|
35
|
+
end
|
36
|
+
|
37
|
+
# Sends a GraphQL tracing event to the notification handler
|
38
|
+
#
|
39
|
+
# @example
|
40
|
+
# . notifications_engine = Dry::Monitor::Notifications.new(:graphql)
|
41
|
+
# . tracer = GraphQL::Tracing::NotificationsTracing.new(notifications_engine)
|
42
|
+
# . tracer.trace("lex") { ... }
|
43
|
+
#
|
44
|
+
# @param [string] key The key for the event
|
45
|
+
# @param [Hash] metadata The metadata for the event
|
46
|
+
# @yield The block to execute for the event
|
47
|
+
def trace(key, metadata, &blk)
|
48
|
+
prefixed_key = KEYS[key] || "#{key}.graphql"
|
49
|
+
|
50
|
+
# Cache the new keys while making sure not to induce a memory leak
|
51
|
+
if KEYS.size < MAX_KEYS_SIZE
|
52
|
+
KEYS[key] ||= prefixed_key
|
53
|
+
end
|
54
|
+
|
55
|
+
@notifications_engine.instrument(prefixed_key, metadata, &blk)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -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 = {})
|
@@ -32,6 +36,7 @@ module GraphQL
|
|
32
36
|
trace_field = true # implemented with instrumenter
|
33
37
|
else
|
34
38
|
field = data[:field]
|
39
|
+
# HERE
|
35
40
|
return_type = field.type.unwrap
|
36
41
|
trace_field = if return_type.kind.scalar? || return_type.kind.enum?
|
37
42
|
(field.trace.nil? && @trace_scalars) || field.trace
|
@@ -41,7 +46,7 @@ module GraphQL
|
|
41
46
|
|
42
47
|
platform_key = if trace_field
|
43
48
|
context = data.fetch(:query).context
|
44
|
-
cached_platform_key(context, field) { platform_field_key(data[:owner], field) }
|
49
|
+
cached_platform_key(context, field, :field) { platform_field_key(data[:owner], field) }
|
45
50
|
else
|
46
51
|
nil
|
47
52
|
end
|
@@ -57,14 +62,14 @@ module GraphQL
|
|
57
62
|
when "authorized", "authorized_lazy"
|
58
63
|
type = data.fetch(:type)
|
59
64
|
context = data.fetch(:context)
|
60
|
-
platform_key = cached_platform_key(context, type) { platform_authorized_key(type) }
|
65
|
+
platform_key = cached_platform_key(context, type, :authorized) { platform_authorized_key(type) }
|
61
66
|
platform_trace(platform_key, key, data) do
|
62
67
|
yield
|
63
68
|
end
|
64
69
|
when "resolve_type", "resolve_type_lazy"
|
65
70
|
type = data.fetch(:type)
|
66
71
|
context = data.fetch(:context)
|
67
|
-
platform_key = cached_platform_key(context, type) { platform_resolve_type_key(type) }
|
72
|
+
platform_key = cached_platform_key(context, type, :resolve_type) { platform_resolve_type_key(type) }
|
68
73
|
platform_trace(platform_key, key, data) do
|
69
74
|
yield
|
70
75
|
end
|
@@ -95,24 +100,31 @@ module GraphQL
|
|
95
100
|
end
|
96
101
|
|
97
102
|
def self.use(schema_defn, options = {})
|
98
|
-
tracer = self.new(options)
|
99
|
-
schema_defn.
|
103
|
+
tracer = self.new(**options)
|
104
|
+
if !schema_defn.is_a?(Class)
|
105
|
+
schema_defn.instrument(:field, tracer)
|
106
|
+
end
|
100
107
|
schema_defn.tracer(tracer)
|
101
108
|
end
|
102
109
|
|
103
110
|
private
|
104
111
|
|
105
|
-
# Get the transaction name based on the operation type and name
|
112
|
+
# Get the transaction name based on the operation type and name if possible, or fall back to a user provided
|
113
|
+
# one. Useful for anonymous queries.
|
106
114
|
def transaction_name(query)
|
107
115
|
selected_op = query.selected_operation
|
108
|
-
if selected_op
|
116
|
+
txn_name = if selected_op
|
109
117
|
op_type = selected_op.operation_type
|
110
|
-
op_name = selected_op.name || "anonymous"
|
118
|
+
op_name = selected_op.name || fallback_transaction_name(query.context) || "anonymous"
|
119
|
+
"#{op_type}.#{op_name}"
|
111
120
|
else
|
112
|
-
|
113
|
-
op_name = "anonymous"
|
121
|
+
"query.anonymous"
|
114
122
|
end
|
115
|
-
"GraphQL/#{
|
123
|
+
"GraphQL/#{txn_name}"
|
124
|
+
end
|
125
|
+
|
126
|
+
def fallback_transaction_name(context)
|
127
|
+
context[:tracing_fallback_transaction_name]
|
116
128
|
end
|
117
129
|
|
118
130
|
attr_reader :options
|
@@ -128,7 +140,7 @@ module GraphQL
|
|
128
140
|
# If the key isn't present, the given block is called and the result is cached for `key`.
|
129
141
|
#
|
130
142
|
# @return [String]
|
131
|
-
def cached_platform_key(ctx, key)
|
143
|
+
def cached_platform_key(ctx, key, trace_phase)
|
132
144
|
cache = ctx.namespace(self.class)[:platform_key_cache] ||= {}
|
133
145
|
cache.fetch(key) { cache[key] = yield }
|
134
146
|
end
|
@@ -16,7 +16,10 @@ module GraphQL
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def collect(object)
|
19
|
-
|
19
|
+
default_labels = { key: object['key'], platform_key: object['platform_key'] }
|
20
|
+
custom = object['custom_labels']
|
21
|
+
labels = custom.nil? ? default_labels : default_labels.merge(custom)
|
22
|
+
|
20
23
|
@graphql_gauge.observe object['duration'], labels
|
21
24
|
end
|
22
25
|
|
@@ -18,7 +18,7 @@ module GraphQL
|
|
18
18
|
# This is not advised if you run more than one query per HTTP request, for example, with `graphql-client` or multiplexing.
|
19
19
|
# It can also be specified per-query with `context[:set_skylight_endpoint_name]`.
|
20
20
|
def initialize(options = {})
|
21
|
-
warn("GraphQL::Tracing::SkylightTracing is deprecated, please enable Skylight's GraphQL probe instead: https://www.skylight.io/support/getting-more-from-skylight#graphql.")
|
21
|
+
GraphQL::Deprecation.warn("GraphQL::Tracing::SkylightTracing is deprecated and will be removed in GraphQL-Ruby 2.0, please enable Skylight's GraphQL probe instead: https://www.skylight.io/support/getting-more-from-skylight#graphql.")
|
22
22
|
@set_endpoint_name = options.fetch(:set_endpoint_name, false)
|
23
23
|
super
|
24
24
|
end
|
data/lib/graphql/tracing.rb
CHANGED
@@ -42,8 +42,8 @@ module GraphQL
|
|
42
42
|
# execute_multiplex | `{ multiplex: GraphQL::Execution::Multiplex }`
|
43
43
|
# execute_query | `{ query: GraphQL::Query }`
|
44
44
|
# execute_query_lazy | `{ query: GraphQL::Query?, multiplex: GraphQL::Execution::Multiplex? }`
|
45
|
-
# execute_field | `{
|
46
|
-
# execute_field_lazy | `{
|
45
|
+
# execute_field | `{ owner: Class, field: GraphQL::Schema::Field, query: GraphQL::Query, path: Array<String, Integer>, ast_node: GraphQL::Language::Nodes::Field}`
|
46
|
+
# execute_field_lazy | `{ owner: Class, field: GraphQL::Schema::Field, query: GraphQL::Query, path: Array<String, Integer>, ast_node: GraphQL::Language::Nodes::Field}`
|
47
47
|
# authorized | `{ context: GraphQL::Query::Context, type: Class, object: Object, path: Array<String, Integer> }`
|
48
48
|
# authorized_lazy | `{ context: GraphQL::Query::Context, type: Class, object: Object, path: Array<String, Integer> }`
|
49
49
|
# resolve_type | `{ context: GraphQL::Query::Context, type: Class, object: Object, path: Array<String, Integer> }`
|
@@ -6,7 +6,7 @@ module GraphQL
|
|
6
6
|
description "Represents non-fractional signed whole numeric values. Since the value may exceed the size of a 32-bit integer, it's encoded as a string."
|
7
7
|
|
8
8
|
def self.coerce_input(value, _ctx)
|
9
|
-
value &&
|
9
|
+
value && parse_int(value)
|
10
10
|
rescue ArgumentError
|
11
11
|
nil
|
12
12
|
end
|
@@ -14,6 +14,10 @@ module GraphQL
|
|
14
14
|
def self.coerce_result(value, _ctx)
|
15
15
|
value.to_i.to_s
|
16
16
|
end
|
17
|
+
|
18
|
+
def self.parse_int(value)
|
19
|
+
value.is_a?(Numeric) ? value : Integer(value, 10)
|
20
|
+
end
|
17
21
|
end
|
18
22
|
end
|
19
23
|
end
|
data/lib/graphql/types/int.rb
CHANGED
@@ -9,8 +9,15 @@ module GraphQL
|
|
9
9
|
MIN = -(2**31)
|
10
10
|
MAX = (2**31) - 1
|
11
11
|
|
12
|
-
def self.coerce_input(value,
|
13
|
-
value.is_a?(Integer)
|
12
|
+
def self.coerce_input(value, ctx)
|
13
|
+
return if !value.is_a?(Integer)
|
14
|
+
|
15
|
+
if value >= MIN && value <= MAX
|
16
|
+
value
|
17
|
+
else
|
18
|
+
err = GraphQL::IntegerDecodingError.new(value)
|
19
|
+
ctx.schema.type_error(err, ctx)
|
20
|
+
end
|
14
21
|
end
|
15
22
|
|
16
23
|
def self.coerce_result(value, ctx)
|
@@ -18,7 +25,7 @@ module GraphQL
|
|
18
25
|
if value >= MIN && value <= MAX
|
19
26
|
value
|
20
27
|
else
|
21
|
-
err = GraphQL::IntegerEncodingError.new(value)
|
28
|
+
err = GraphQL::IntegerEncodingError.new(value, context: ctx)
|
22
29
|
ctx.schema.type_error(err, ctx)
|
23
30
|
end
|
24
31
|
end
|
@@ -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
|