graphql 2.0.13 → 2.3.10
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/install/mutation_root_generator.rb +2 -2
- data/lib/generators/graphql/install/templates/base_mutation.erb +2 -0
- data/lib/generators/graphql/install/templates/mutation_type.erb +2 -0
- data/lib/generators/graphql/install_generator.rb +3 -0
- data/lib/generators/graphql/mutation_delete_generator.rb +1 -1
- data/lib/generators/graphql/mutation_update_generator.rb +1 -1
- data/lib/generators/graphql/relay.rb +18 -1
- data/lib/generators/graphql/templates/base_argument.erb +2 -0
- data/lib/generators/graphql/templates/base_connection.erb +2 -0
- data/lib/generators/graphql/templates/base_edge.erb +2 -0
- data/lib/generators/graphql/templates/base_enum.erb +2 -0
- data/lib/generators/graphql/templates/base_field.erb +2 -0
- data/lib/generators/graphql/templates/base_input_object.erb +2 -0
- data/lib/generators/graphql/templates/base_interface.erb +2 -0
- data/lib/generators/graphql/templates/base_object.erb +2 -0
- data/lib/generators/graphql/templates/base_resolver.erb +6 -0
- data/lib/generators/graphql/templates/base_scalar.erb +2 -0
- data/lib/generators/graphql/templates/base_union.erb +2 -0
- data/lib/generators/graphql/templates/graphql_controller.erb +2 -0
- data/lib/generators/graphql/templates/loader.erb +2 -0
- data/lib/generators/graphql/templates/mutation.erb +2 -0
- data/lib/generators/graphql/templates/node_type.erb +2 -0
- data/lib/generators/graphql/templates/query_type.erb +2 -0
- data/lib/generators/graphql/templates/schema.erb +8 -0
- data/lib/graphql/analysis/analyzer.rb +89 -0
- data/lib/graphql/analysis/field_usage.rb +82 -0
- data/lib/graphql/analysis/max_query_complexity.rb +20 -0
- data/lib/graphql/analysis/max_query_depth.rb +20 -0
- data/lib/graphql/analysis/query_complexity.rb +183 -0
- data/lib/graphql/analysis/query_depth.rb +58 -0
- data/lib/graphql/analysis/visitor.rb +283 -0
- data/lib/graphql/analysis.rb +92 -1
- data/lib/graphql/backtrace/inspect_result.rb +0 -12
- data/lib/graphql/backtrace/table.rb +2 -2
- data/lib/graphql/backtrace/trace.rb +93 -0
- data/lib/graphql/backtrace/tracer.rb +1 -1
- data/lib/graphql/backtrace.rb +2 -1
- data/lib/graphql/coercion_error.rb +1 -9
- data/lib/graphql/dataloader/async_dataloader.rb +88 -0
- data/lib/graphql/dataloader/null_dataloader.rb +1 -1
- data/lib/graphql/dataloader/request.rb +5 -0
- data/lib/graphql/dataloader/source.rb +89 -45
- data/lib/graphql/dataloader.rb +115 -142
- data/lib/graphql/duration_encoding_error.rb +16 -0
- data/lib/graphql/execution/interpreter/argument_value.rb +5 -1
- data/lib/graphql/execution/interpreter/arguments.rb +1 -1
- data/lib/graphql/execution/interpreter/arguments_cache.rb +33 -33
- data/lib/graphql/execution/interpreter/resolve.rb +19 -0
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +175 -0
- data/lib/graphql/execution/interpreter/runtime.rb +331 -455
- data/lib/graphql/execution/interpreter.rb +125 -61
- data/lib/graphql/execution/lazy.rb +6 -12
- data/lib/graphql/execution/lookahead.rb +124 -46
- data/lib/graphql/execution/multiplex.rb +3 -117
- data/lib/graphql/execution.rb +0 -1
- data/lib/graphql/introspection/directive_type.rb +3 -3
- data/lib/graphql/introspection/dynamic_fields.rb +1 -1
- data/lib/graphql/introspection/entry_points.rb +11 -5
- data/lib/graphql/introspection/field_type.rb +2 -2
- data/lib/graphql/introspection/schema_type.rb +10 -13
- data/lib/graphql/introspection/type_type.rb +17 -10
- data/lib/graphql/introspection.rb +3 -2
- data/lib/graphql/language/block_string.rb +34 -18
- data/lib/graphql/language/definition_slice.rb +1 -1
- data/lib/graphql/language/document_from_schema_definition.rb +75 -59
- data/lib/graphql/language/lexer.rb +358 -1506
- data/lib/graphql/language/nodes.rb +166 -93
- data/lib/graphql/language/parser.rb +795 -1953
- data/lib/graphql/language/printer.rb +340 -160
- data/lib/graphql/language/sanitized_printer.rb +21 -23
- data/lib/graphql/language/static_visitor.rb +167 -0
- data/lib/graphql/language/visitor.rb +188 -141
- data/lib/graphql/language.rb +61 -1
- data/lib/graphql/load_application_object_failed_error.rb +5 -1
- data/lib/graphql/pagination/active_record_relation_connection.rb +0 -8
- data/lib/graphql/pagination/array_connection.rb +6 -6
- data/lib/graphql/pagination/connection.rb +33 -6
- data/lib/graphql/pagination/mongoid_relation_connection.rb +1 -2
- data/lib/graphql/query/context/scoped_context.rb +101 -0
- data/lib/graphql/query/context.rb +117 -112
- data/lib/graphql/query/null_context.rb +12 -25
- data/lib/graphql/query/validation_pipeline.rb +6 -5
- data/lib/graphql/query/variables.rb +3 -3
- data/lib/graphql/query.rb +86 -30
- data/lib/graphql/railtie.rb +9 -6
- data/lib/graphql/rake_task.rb +29 -11
- data/lib/graphql/rubocop/graphql/base_cop.rb +1 -1
- data/lib/graphql/schema/addition.rb +59 -23
- data/lib/graphql/schema/always_visible.rb +11 -0
- data/lib/graphql/schema/argument.rb +55 -26
- data/lib/graphql/schema/base_64_encoder.rb +3 -5
- data/lib/graphql/schema/build_from_definition.rb +56 -32
- data/lib/graphql/schema/directive/one_of.rb +24 -0
- data/lib/graphql/schema/directive/specified_by.rb +14 -0
- data/lib/graphql/schema/directive/transform.rb +1 -1
- data/lib/graphql/schema/directive.rb +15 -3
- data/lib/graphql/schema/enum.rb +35 -24
- data/lib/graphql/schema/enum_value.rb +2 -3
- data/lib/graphql/schema/field/connection_extension.rb +2 -16
- data/lib/graphql/schema/field/scope_extension.rb +8 -1
- data/lib/graphql/schema/field.rb +147 -107
- data/lib/graphql/schema/field_extension.rb +1 -4
- data/lib/graphql/schema/find_inherited_value.rb +2 -7
- data/lib/graphql/schema/has_single_input_argument.rb +158 -0
- data/lib/graphql/schema/input_object.rb +47 -11
- data/lib/graphql/schema/interface.rb +15 -21
- data/lib/graphql/schema/introspection_system.rb +7 -17
- data/lib/graphql/schema/late_bound_type.rb +10 -0
- data/lib/graphql/schema/list.rb +2 -2
- data/lib/graphql/schema/loader.rb +2 -3
- data/lib/graphql/schema/member/base_dsl_methods.rb +18 -14
- data/lib/graphql/schema/member/build_type.rb +11 -3
- data/lib/graphql/schema/member/has_arguments.rb +170 -130
- data/lib/graphql/schema/member/has_ast_node.rb +12 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +3 -4
- data/lib/graphql/schema/member/has_directives.rb +81 -61
- data/lib/graphql/schema/member/has_fields.rb +100 -38
- data/lib/graphql/schema/member/has_interfaces.rb +65 -10
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +5 -1
- data/lib/graphql/schema/member/has_validators.rb +32 -6
- data/lib/graphql/schema/member/relay_shortcuts.rb +19 -0
- data/lib/graphql/schema/member/scoped.rb +19 -0
- data/lib/graphql/schema/member/type_system_helpers.rb +16 -0
- data/lib/graphql/schema/member/validates_input.rb +3 -3
- data/lib/graphql/schema/mutation.rb +7 -0
- data/lib/graphql/schema/object.rb +16 -5
- data/lib/graphql/schema/printer.rb +11 -8
- data/lib/graphql/schema/relay_classic_mutation.rb +7 -129
- data/lib/graphql/schema/resolver/has_payload_type.rb +9 -9
- data/lib/graphql/schema/resolver.rb +47 -32
- data/lib/graphql/schema/scalar.rb +3 -3
- data/lib/graphql/schema/subscription.rb +11 -4
- data/lib/graphql/schema/subset.rb +397 -0
- data/lib/graphql/schema/timeout.rb +25 -29
- data/lib/graphql/schema/type_expression.rb +2 -2
- data/lib/graphql/schema/type_membership.rb +3 -0
- data/lib/graphql/schema/union.rb +11 -2
- data/lib/graphql/schema/unique_within_type.rb +1 -1
- data/lib/graphql/schema/validator/all_validator.rb +60 -0
- data/lib/graphql/schema/validator.rb +4 -2
- data/lib/graphql/schema/warden.rb +238 -93
- data/lib/graphql/schema.rb +498 -103
- data/lib/graphql/static_validation/all_rules.rb +2 -1
- data/lib/graphql/static_validation/base_visitor.rb +7 -6
- data/lib/graphql/static_validation/definition_dependencies.rb +7 -1
- data/lib/graphql/static_validation/literal_validator.rb +24 -7
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +1 -1
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -2
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +12 -4
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +10 -10
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +1 -1
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
- data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
- data/lib/graphql/static_validation/rules/query_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -4
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +5 -5
- data/lib/graphql/static_validation/rules/subscription_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +18 -27
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +1 -1
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
- data/lib/graphql/static_validation/validation_context.rb +5 -5
- data/lib/graphql/static_validation/validator.rb +4 -1
- data/lib/graphql/static_validation.rb +0 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +11 -4
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +11 -5
- data/lib/graphql/subscriptions/event.rb +11 -10
- data/lib/graphql/subscriptions/serialize.rb +2 -0
- data/lib/graphql/subscriptions.rb +20 -13
- data/lib/graphql/testing/helpers.rb +151 -0
- data/lib/graphql/testing.rb +2 -0
- data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
- data/lib/graphql/tracing/appoptics_trace.rb +251 -0
- data/lib/graphql/tracing/appoptics_tracing.rb +2 -2
- data/lib/graphql/tracing/appsignal_trace.rb +77 -0
- data/lib/graphql/tracing/data_dog_trace.rb +183 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +9 -21
- data/lib/graphql/{execution/instrumentation.rb → tracing/legacy_hooks_trace.rb} +10 -28
- data/lib/graphql/tracing/legacy_trace.rb +69 -0
- data/lib/graphql/tracing/new_relic_trace.rb +75 -0
- data/lib/graphql/tracing/notifications_trace.rb +45 -0
- data/lib/graphql/tracing/platform_trace.rb +118 -0
- data/lib/graphql/tracing/platform_tracing.rb +17 -3
- data/lib/graphql/tracing/{prometheus_tracing → prometheus_trace}/graphql_collector.rb +4 -2
- data/lib/graphql/tracing/prometheus_trace.rb +89 -0
- data/lib/graphql/tracing/prometheus_tracing.rb +3 -3
- data/lib/graphql/tracing/scout_trace.rb +72 -0
- data/lib/graphql/tracing/sentry_trace.rb +112 -0
- data/lib/graphql/tracing/statsd_trace.rb +56 -0
- data/lib/graphql/tracing/trace.rb +76 -0
- data/lib/graphql/tracing.rb +20 -40
- data/lib/graphql/type_kinds.rb +7 -4
- data/lib/graphql/types/iso_8601_duration.rb +77 -0
- data/lib/graphql/types/relay/base_connection.rb +1 -1
- data/lib/graphql/types/relay/connection_behaviors.rb +68 -6
- data/lib/graphql/types/relay/edge_behaviors.rb +33 -5
- data/lib/graphql/types/relay/node_behaviors.rb +8 -2
- data/lib/graphql/types/relay/page_info_behaviors.rb +11 -2
- data/lib/graphql/types/relay.rb +0 -1
- data/lib/graphql/types/string.rb +1 -1
- data/lib/graphql/types.rb +1 -0
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +27 -20
- data/readme.md +13 -3
- metadata +96 -47
- data/lib/graphql/analysis/ast/analyzer.rb +0 -84
- data/lib/graphql/analysis/ast/field_usage.rb +0 -57
- data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -22
- data/lib/graphql/analysis/ast/max_query_depth.rb +0 -22
- data/lib/graphql/analysis/ast/query_complexity.rb +0 -230
- data/lib/graphql/analysis/ast/query_depth.rb +0 -55
- data/lib/graphql/analysis/ast/visitor.rb +0 -269
- data/lib/graphql/analysis/ast.rb +0 -81
- data/lib/graphql/deprecation.rb +0 -9
- data/lib/graphql/filter.rb +0 -53
- data/lib/graphql/language/lexer.rl +0 -280
- data/lib/graphql/language/parser.y +0 -554
- data/lib/graphql/language/token.rb +0 -34
- data/lib/graphql/schema/base_64_bp.rb +0 -26
- data/lib/graphql/schema/invalid_type_error.rb +0 -7
- data/lib/graphql/static_validation/type_stack.rb +0 -216
- data/lib/graphql/subscriptions/instrumentation.rb +0 -28
- data/lib/graphql/types/relay/default_relay.rb +0 -21
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Tracing
|
5
|
+
module StatsdTrace
|
6
|
+
include PlatformTrace
|
7
|
+
|
8
|
+
# @param statsd [Object] A statsd client
|
9
|
+
def initialize(statsd:, **rest)
|
10
|
+
@statsd = statsd
|
11
|
+
super(**rest)
|
12
|
+
end
|
13
|
+
|
14
|
+
{
|
15
|
+
'lex' => "graphql.lex",
|
16
|
+
'parse' => "graphql.parse",
|
17
|
+
'validate' => "graphql.validate",
|
18
|
+
'analyze_query' => "graphql.analyze_query",
|
19
|
+
'analyze_multiplex' => "graphql.analyze_multiplex",
|
20
|
+
'execute_multiplex' => "graphql.execute_multiplex",
|
21
|
+
'execute_query' => "graphql.execute_query",
|
22
|
+
'execute_query_lazy' => "graphql.execute_query_lazy",
|
23
|
+
}.each do |trace_method, platform_key|
|
24
|
+
module_eval <<-RUBY, __FILE__, __LINE__
|
25
|
+
def #{trace_method}(**data)
|
26
|
+
@statsd.time("#{platform_key}") do
|
27
|
+
super
|
28
|
+
end
|
29
|
+
end
|
30
|
+
RUBY
|
31
|
+
end
|
32
|
+
|
33
|
+
def platform_execute_field(platform_key, &block)
|
34
|
+
@statsd.time(platform_key, &block)
|
35
|
+
end
|
36
|
+
|
37
|
+
def platform_authorized(key, &block)
|
38
|
+
@statsd.time(key, &block)
|
39
|
+
end
|
40
|
+
|
41
|
+
alias :platform_resolve_type :platform_authorized
|
42
|
+
|
43
|
+
def platform_field_key(field)
|
44
|
+
"graphql.#{field.path}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def platform_authorized_key(type)
|
48
|
+
"graphql.authorized.#{type.graphql_name}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def platform_resolve_type_key(type)
|
52
|
+
"graphql.resolve_type.#{type.graphql_name}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module Tracing
|
4
|
+
# This is the base class for a `trace` instance whose methods are called during query execution.
|
5
|
+
# "Trace modes" are subclasses of this with custom tracing modules mixed in.
|
6
|
+
#
|
7
|
+
# A trace module may implement any of the methods on `Trace`, being sure to call `super`
|
8
|
+
# to continue any tracing hooks and call the actual runtime behavior. See {GraphQL::Backtrace::Trace} for example.
|
9
|
+
#
|
10
|
+
class Trace
|
11
|
+
# @param multiplex [GraphQL::Execution::Multiplex, nil]
|
12
|
+
# @param query [GraphQL::Query, nil]
|
13
|
+
def initialize(multiplex: nil, query: nil, **_options)
|
14
|
+
@multiplex = multiplex
|
15
|
+
@query = query
|
16
|
+
end
|
17
|
+
|
18
|
+
# The Ruby parser doesn't call this method (`graphql/c_parser` does.)
|
19
|
+
def lex(query_string:)
|
20
|
+
yield
|
21
|
+
end
|
22
|
+
|
23
|
+
def parse(query_string:)
|
24
|
+
yield
|
25
|
+
end
|
26
|
+
|
27
|
+
def validate(query:, validate:)
|
28
|
+
yield
|
29
|
+
end
|
30
|
+
|
31
|
+
def analyze_multiplex(multiplex:)
|
32
|
+
yield
|
33
|
+
end
|
34
|
+
|
35
|
+
def analyze_query(query:)
|
36
|
+
yield
|
37
|
+
end
|
38
|
+
|
39
|
+
def execute_multiplex(multiplex:)
|
40
|
+
yield
|
41
|
+
end
|
42
|
+
|
43
|
+
def execute_query(query:)
|
44
|
+
yield
|
45
|
+
end
|
46
|
+
|
47
|
+
def execute_query_lazy(query:, multiplex:)
|
48
|
+
yield
|
49
|
+
end
|
50
|
+
|
51
|
+
def execute_field(field:, query:, ast_node:, arguments:, object:)
|
52
|
+
yield
|
53
|
+
end
|
54
|
+
|
55
|
+
def execute_field_lazy(field:, query:, ast_node:, arguments:, object:)
|
56
|
+
yield
|
57
|
+
end
|
58
|
+
|
59
|
+
def authorized(query:, type:, object:)
|
60
|
+
yield
|
61
|
+
end
|
62
|
+
|
63
|
+
def authorized_lazy(query:, type:, object:)
|
64
|
+
yield
|
65
|
+
end
|
66
|
+
|
67
|
+
def resolve_type(query:, type:, object:)
|
68
|
+
yield
|
69
|
+
end
|
70
|
+
|
71
|
+
def resolve_type_lazy(query:, type:, object:)
|
72
|
+
yield
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/lib/graphql/tracing.rb
CHANGED
@@ -1,4 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
require "graphql/tracing/trace"
|
3
|
+
require "graphql/tracing/legacy_trace"
|
4
|
+
require "graphql/tracing/legacy_hooks_trace"
|
5
|
+
|
6
|
+
# Legacy tracing:
|
2
7
|
require "graphql/tracing/active_support_notifications_tracing"
|
3
8
|
require "graphql/tracing/platform_tracing"
|
4
9
|
require "graphql/tracing/appoptics_tracing"
|
@@ -9,51 +14,26 @@ require "graphql/tracing/scout_tracing"
|
|
9
14
|
require "graphql/tracing/statsd_tracing"
|
10
15
|
require "graphql/tracing/prometheus_tracing"
|
11
16
|
|
17
|
+
# New Tracing:
|
18
|
+
require "graphql/tracing/active_support_notifications_trace"
|
19
|
+
require "graphql/tracing/platform_trace"
|
20
|
+
require "graphql/tracing/appoptics_trace"
|
21
|
+
require "graphql/tracing/appsignal_trace"
|
22
|
+
require "graphql/tracing/data_dog_trace"
|
23
|
+
require "graphql/tracing/new_relic_trace"
|
24
|
+
require "graphql/tracing/notifications_trace"
|
25
|
+
require "graphql/tracing/sentry_trace"
|
26
|
+
require "graphql/tracing/scout_trace"
|
27
|
+
require "graphql/tracing/statsd_trace"
|
28
|
+
require "graphql/tracing/prometheus_trace"
|
12
29
|
if defined?(PrometheusExporter::Server)
|
13
|
-
require "graphql/tracing/
|
30
|
+
require "graphql/tracing/prometheus_trace/graphql_collector"
|
14
31
|
end
|
15
32
|
|
16
33
|
module GraphQL
|
17
|
-
# Library entry point for performance metric reporting.
|
18
|
-
#
|
19
|
-
# @example Sending custom events
|
20
|
-
# query.trace("my_custom_event", { ... }) do
|
21
|
-
# # do stuff ...
|
22
|
-
# end
|
23
|
-
#
|
24
|
-
# @example Adding a tracer to a schema
|
25
|
-
# class MySchema < GraphQL::Schema
|
26
|
-
# tracer MyTracer # <= responds to .trace(key, data, &block)
|
27
|
-
# end
|
28
|
-
#
|
29
|
-
# @example Adding a tracer to a single query
|
30
|
-
# MySchema.execute(query_str, context: { backtrace: true })
|
31
|
-
#
|
32
|
-
# Events:
|
33
|
-
#
|
34
|
-
# Key | Metadata
|
35
|
-
# ----|---------
|
36
|
-
# lex | `{ query_string: String }`
|
37
|
-
# parse | `{ query_string: String }`
|
38
|
-
# validate | `{ query: GraphQL::Query, validate: Boolean }`
|
39
|
-
# analyze_multiplex | `{ multiplex: GraphQL::Execution::Multiplex }`
|
40
|
-
# analyze_query | `{ query: GraphQL::Query }`
|
41
|
-
# execute_multiplex | `{ multiplex: GraphQL::Execution::Multiplex }`
|
42
|
-
# execute_query | `{ query: GraphQL::Query }`
|
43
|
-
# execute_query_lazy | `{ query: GraphQL::Query?, multiplex: GraphQL::Execution::Multiplex? }`
|
44
|
-
# execute_field | `{ owner: Class, field: GraphQL::Schema::Field, query: GraphQL::Query, path: Array<String, Integer>, ast_node: GraphQL::Language::Nodes::Field}`
|
45
|
-
# execute_field_lazy | `{ owner: Class, field: GraphQL::Schema::Field, query: GraphQL::Query, path: Array<String, Integer>, ast_node: GraphQL::Language::Nodes::Field}`
|
46
|
-
# authorized | `{ context: GraphQL::Query::Context, type: Class, object: Object, path: Array<String, Integer> }`
|
47
|
-
# authorized_lazy | `{ context: GraphQL::Query::Context, type: Class, object: Object, path: Array<String, Integer> }`
|
48
|
-
# resolve_type | `{ context: GraphQL::Query::Context, type: Class, object: Object, path: Array<String, Integer> }`
|
49
|
-
# resolve_type_lazy | `{ context: GraphQL::Query::Context, type: Class, object: Object, path: Array<String, Integer> }`
|
50
|
-
#
|
51
|
-
# Note that `execute_field` and `execute_field_lazy` receive different data in different settings:
|
52
|
-
#
|
53
|
-
# - When using {GraphQL::Execution::Interpreter}, they receive `{field:, path:, query:}`
|
54
|
-
# - Otherwise, they receive `{context: ...}`
|
55
|
-
#
|
56
34
|
module Tracing
|
35
|
+
NullTrace = Trace.new
|
36
|
+
|
57
37
|
# Objects may include traceable to gain a `.trace(...)` method.
|
58
38
|
# The object must have a `@tracers` ivar of type `Array<<#trace(k, d, &b)>>`.
|
59
39
|
# @api private
|
data/lib/graphql/type_kinds.rb
CHANGED
@@ -5,17 +5,18 @@ module GraphQL
|
|
5
5
|
# These objects are singletons, eg `GraphQL::TypeKinds::UNION`, `GraphQL::TypeKinds::SCALAR`.
|
6
6
|
class TypeKind
|
7
7
|
attr_reader :name, :description
|
8
|
-
def initialize(name, abstract: false, fields: false, wraps: false, input: false, description: nil)
|
8
|
+
def initialize(name, abstract: false, leaf: false, fields: false, wraps: false, input: false, description: nil)
|
9
9
|
@name = name
|
10
10
|
@abstract = abstract
|
11
11
|
@fields = fields
|
12
12
|
@wraps = wraps
|
13
13
|
@input = input
|
14
|
+
@leaf = leaf
|
14
15
|
@composite = fields? || abstract?
|
15
16
|
@description = description
|
16
17
|
end
|
17
18
|
|
18
|
-
# Does this TypeKind have multiple possible
|
19
|
+
# Does this TypeKind have multiple possible implementers?
|
19
20
|
# @deprecated Use `abstract?` instead of `resolves?`.
|
20
21
|
def resolves?; @abstract; end
|
21
22
|
# Is this TypeKind abstract?
|
@@ -27,6 +28,8 @@ module GraphQL
|
|
27
28
|
# Is this TypeKind a valid query input?
|
28
29
|
def input?; @input; end
|
29
30
|
def to_s; @name; end
|
31
|
+
# Is this TypeKind a primitive value?
|
32
|
+
def leaf?; @leaf; end
|
30
33
|
# Is this TypeKind composed of many values?
|
31
34
|
def composite?; @composite; end
|
32
35
|
|
@@ -64,11 +67,11 @@ module GraphQL
|
|
64
67
|
end
|
65
68
|
|
66
69
|
TYPE_KINDS = [
|
67
|
-
SCALAR = TypeKind.new("SCALAR", input: true, description: 'Indicates this type is a scalar.'),
|
70
|
+
SCALAR = TypeKind.new("SCALAR", input: true, leaf: true, description: 'Indicates this type is a scalar.'),
|
68
71
|
OBJECT = TypeKind.new("OBJECT", fields: true, description: 'Indicates this type is an object. `fields` and `interfaces` are valid fields.'),
|
69
72
|
INTERFACE = TypeKind.new("INTERFACE", abstract: true, fields: true, description: 'Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.'),
|
70
73
|
UNION = TypeKind.new("UNION", abstract: true, description: 'Indicates this type is a union. `possibleTypes` is a valid field.'),
|
71
|
-
ENUM = TypeKind.new("ENUM", input: true, description: 'Indicates this type is an enum. `enumValues` is a valid field.'),
|
74
|
+
ENUM = TypeKind.new("ENUM", input: true, leaf: true, description: 'Indicates this type is an enum. `enumValues` is a valid field.'),
|
72
75
|
INPUT_OBJECT = TypeKind.new("INPUT_OBJECT", input: true, description: 'Indicates this type is an input object. `inputFields` is a valid field.'),
|
73
76
|
LIST = TypeKind.new("LIST", wraps: true, description: 'Indicates this type is a list. `ofType` is a valid field.'),
|
74
77
|
NON_NULL = TypeKind.new("NON_NULL", wraps: true, description: 'Indicates this type is a non-null. `ofType` is a valid field.'),
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module Types
|
4
|
+
# This scalar takes `Duration`s and transmits them as strings,
|
5
|
+
# using ISO 8601 format. ActiveSupport >= 5.0 must be loaded to use
|
6
|
+
# this scalar.
|
7
|
+
#
|
8
|
+
# Use it for fields or arguments as follows:
|
9
|
+
#
|
10
|
+
# field :age, GraphQL::Types::ISO8601Duration, null: false
|
11
|
+
#
|
12
|
+
# argument :interval, GraphQL::Types::ISO8601Duration, null: false
|
13
|
+
#
|
14
|
+
# Alternatively, use this built-in scalar as inspiration for your
|
15
|
+
# own Duration type.
|
16
|
+
class ISO8601Duration < GraphQL::Schema::Scalar
|
17
|
+
description "An ISO 8601-encoded duration"
|
18
|
+
|
19
|
+
# @return [Integer, nil]
|
20
|
+
def self.seconds_precision
|
21
|
+
# ActiveSupport::Duration precision defaults to whatever input was given
|
22
|
+
@seconds_precision
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param [Integer, nil] value
|
26
|
+
def self.seconds_precision=(value)
|
27
|
+
@seconds_precision = value
|
28
|
+
end
|
29
|
+
|
30
|
+
# @param value [ActiveSupport::Duration, String]
|
31
|
+
# @return [String]
|
32
|
+
# @raise [GraphQL::Error] if ActiveSupport::Duration is not defined or if an incompatible object is passed
|
33
|
+
def self.coerce_result(value, _ctx)
|
34
|
+
unless defined?(ActiveSupport::Duration)
|
35
|
+
raise GraphQL::Error, "ActiveSupport >= 5.0 must be loaded to use the built-in ISO8601Duration type."
|
36
|
+
end
|
37
|
+
|
38
|
+
begin
|
39
|
+
case value
|
40
|
+
when ActiveSupport::Duration
|
41
|
+
value.iso8601(precision: seconds_precision)
|
42
|
+
when ::String
|
43
|
+
ActiveSupport::Duration.parse(value).iso8601(precision: seconds_precision)
|
44
|
+
else
|
45
|
+
# Try calling as ActiveSupport::Duration compatible as a fallback
|
46
|
+
value.iso8601(precision: seconds_precision)
|
47
|
+
end
|
48
|
+
rescue StandardError => error
|
49
|
+
raise GraphQL::Error, "An incompatible object (#{value.class}) was given to #{self}. Make sure that only ActiveSupport::Durations and well-formatted Strings are used with this type. (#{error.message})"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# @param value [String, ActiveSupport::Duration]
|
54
|
+
# @return [ActiveSupport::Duration, nil]
|
55
|
+
# @raise [GraphQL::Error] if ActiveSupport::Duration is not defined
|
56
|
+
# @raise [GraphQL::DurationEncodingError] if duration cannot be parsed
|
57
|
+
def self.coerce_input(value, ctx)
|
58
|
+
unless defined?(ActiveSupport::Duration)
|
59
|
+
raise GraphQL::Error, "ActiveSupport >= 5.0 must be loaded to use the built-in ISO8601Duration type."
|
60
|
+
end
|
61
|
+
|
62
|
+
begin
|
63
|
+
if value.is_a?(ActiveSupport::Duration)
|
64
|
+
value
|
65
|
+
elsif value.nil?
|
66
|
+
nil
|
67
|
+
else
|
68
|
+
ActiveSupport::Duration.parse(value)
|
69
|
+
end
|
70
|
+
rescue ArgumentError, TypeError
|
71
|
+
err = GraphQL::DurationEncodingError.new(value)
|
72
|
+
ctx.schema.type_error(err, ctx)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -35,7 +35,7 @@ module GraphQL
|
|
35
35
|
# # Alternatively, you can call the class methods followed by your edge type
|
36
36
|
# # edges_nullable true
|
37
37
|
# # edge_nullable true
|
38
|
-
# #
|
38
|
+
# # node_nullable true
|
39
39
|
# # has_nodes_field true
|
40
40
|
# # edge_type Types::PostEdge
|
41
41
|
# end
|
@@ -9,16 +9,44 @@ module GraphQL
|
|
9
9
|
|
10
10
|
def self.included(child_class)
|
11
11
|
child_class.extend(ClassMethods)
|
12
|
-
child_class.extend(Relay::DefaultRelay)
|
13
|
-
child_class.default_relay(true)
|
14
12
|
child_class.has_nodes_field(true)
|
15
13
|
child_class.node_nullable(true)
|
16
14
|
child_class.edges_nullable(true)
|
17
15
|
child_class.edge_nullable(true)
|
16
|
+
child_class.module_eval {
|
17
|
+
self.edge_type = nil
|
18
|
+
self.node_type = nil
|
19
|
+
self.edge_class = nil
|
20
|
+
}
|
21
|
+
child_class.default_broadcastable(nil)
|
18
22
|
add_page_info_field(child_class)
|
19
23
|
end
|
20
24
|
|
21
25
|
module ClassMethods
|
26
|
+
def inherited(child_class)
|
27
|
+
super
|
28
|
+
child_class.has_nodes_field(has_nodes_field)
|
29
|
+
child_class.node_nullable(node_nullable)
|
30
|
+
child_class.edges_nullable(edges_nullable)
|
31
|
+
child_class.edge_nullable(edge_nullable)
|
32
|
+
child_class.edge_type = nil
|
33
|
+
child_class.node_type = nil
|
34
|
+
child_class.edge_class = nil
|
35
|
+
child_class.default_broadcastable(default_broadcastable?)
|
36
|
+
end
|
37
|
+
|
38
|
+
def default_relay?
|
39
|
+
true
|
40
|
+
end
|
41
|
+
|
42
|
+
def default_broadcastable?
|
43
|
+
@default_broadcastable
|
44
|
+
end
|
45
|
+
|
46
|
+
def default_broadcastable(new_value)
|
47
|
+
@default_broadcastable = new_value
|
48
|
+
end
|
49
|
+
|
22
50
|
# @return [Class]
|
23
51
|
attr_reader :node_type
|
24
52
|
|
@@ -49,6 +77,7 @@ module GraphQL
|
|
49
77
|
type: [edge_type_class, null: edge_nullable],
|
50
78
|
null: edges_nullable,
|
51
79
|
description: "A list of edges.",
|
80
|
+
scope: false, # Assume that the connection was already scoped.
|
52
81
|
connection: false,
|
53
82
|
}
|
54
83
|
|
@@ -68,6 +97,19 @@ module GraphQL
|
|
68
97
|
node_type.scope_items(items, context)
|
69
98
|
end
|
70
99
|
|
100
|
+
# The connection will skip auth on its nodes if the node_type is configured for that
|
101
|
+
def reauthorize_scoped_objects(new_value = nil)
|
102
|
+
if new_value.nil?
|
103
|
+
if @reauthorize_scoped_objects != nil
|
104
|
+
@reauthorize_scoped_objects
|
105
|
+
else
|
106
|
+
node_type.reauthorize_scoped_objects
|
107
|
+
end
|
108
|
+
else
|
109
|
+
@reauthorize_scoped_objects = new_value
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
71
113
|
# Add the shortcut `nodes` field to this connection and its subclasses
|
72
114
|
def nodes_field(node_nullable: self.node_nullable, field_options: nil)
|
73
115
|
define_nodes_field(node_nullable, field_options: field_options)
|
@@ -77,10 +119,6 @@ module GraphQL
|
|
77
119
|
true # Let nodes be filtered out
|
78
120
|
end
|
79
121
|
|
80
|
-
def accessible?(ctx)
|
81
|
-
node_type.accessible?(ctx)
|
82
|
-
end
|
83
|
-
|
84
122
|
def visible?(ctx)
|
85
123
|
# if this is an abstract base class, there may be no `node_type`
|
86
124
|
node_type ? node_type.visible?(ctx) : super
|
@@ -126,6 +164,10 @@ module GraphQL
|
|
126
164
|
end
|
127
165
|
end
|
128
166
|
|
167
|
+
protected
|
168
|
+
|
169
|
+
attr_writer :edge_type, :node_type, :edge_class
|
170
|
+
|
129
171
|
private
|
130
172
|
|
131
173
|
def define_nodes_field(nullable, field_options: nil)
|
@@ -135,6 +177,8 @@ module GraphQL
|
|
135
177
|
null: nullable,
|
136
178
|
description: "A list of nodes.",
|
137
179
|
connection: false,
|
180
|
+
# Assume that the connection was scoped before this step:
|
181
|
+
scope: false,
|
138
182
|
}
|
139
183
|
if field_options
|
140
184
|
base_field_options.merge!(field_options)
|
@@ -148,6 +192,24 @@ module GraphQL
|
|
148
192
|
obj_type.field :page_info, GraphQL::Types::Relay::PageInfo, null: false, description: "Information to aid in pagination."
|
149
193
|
end
|
150
194
|
end
|
195
|
+
|
196
|
+
def edges
|
197
|
+
# Assume that whatever authorization needed to happen
|
198
|
+
# already happened at the connection level.
|
199
|
+
current_runtime_state = Thread.current[:__graphql_runtime_info]
|
200
|
+
query_runtime_state = current_runtime_state[context.query]
|
201
|
+
query_runtime_state.was_authorized_by_scope_items = @object.was_authorized_by_scope_items?
|
202
|
+
@object.edges
|
203
|
+
end
|
204
|
+
|
205
|
+
def nodes
|
206
|
+
# Assume that whatever authorization needed to happen
|
207
|
+
# already happened at the connection level.
|
208
|
+
current_runtime_state = Thread.current[:__graphql_runtime_info]
|
209
|
+
query_runtime_state = current_runtime_state[context.query]
|
210
|
+
query_runtime_state.was_authorized_by_scope_items = @object.was_authorized_by_scope_items?
|
211
|
+
@object.nodes
|
212
|
+
end
|
151
213
|
end
|
152
214
|
end
|
153
215
|
end
|
@@ -8,10 +8,38 @@ module GraphQL
|
|
8
8
|
child_class.description("An edge in a connection.")
|
9
9
|
child_class.field(:cursor, String, null: false, description: "A cursor for use in pagination.")
|
10
10
|
child_class.extend(ClassMethods)
|
11
|
+
child_class.class_eval { self.node_type = nil }
|
11
12
|
child_class.node_nullable(true)
|
13
|
+
child_class.default_broadcastable(nil)
|
14
|
+
end
|
15
|
+
|
16
|
+
def node
|
17
|
+
current_runtime_state = Thread.current[:__graphql_runtime_info]
|
18
|
+
query_runtime_state = current_runtime_state[context.query]
|
19
|
+
query_runtime_state.was_authorized_by_scope_items = @object.was_authorized_by_scope_items?
|
20
|
+
@object.node
|
12
21
|
end
|
13
22
|
|
14
23
|
module ClassMethods
|
24
|
+
def inherited(child_class)
|
25
|
+
super
|
26
|
+
child_class.node_type = nil
|
27
|
+
child_class.node_nullable = nil
|
28
|
+
child_class.default_broadcastable(default_broadcastable?)
|
29
|
+
end
|
30
|
+
|
31
|
+
def default_relay?
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
35
|
+
def default_broadcastable?
|
36
|
+
@default_broadcastable
|
37
|
+
end
|
38
|
+
|
39
|
+
def default_broadcastable(new_value)
|
40
|
+
@default_broadcastable = new_value
|
41
|
+
end
|
42
|
+
|
15
43
|
# Get or set the Object type that this edge wraps.
|
16
44
|
#
|
17
45
|
# @param node_type [Class] A `Schema::Object` subclass
|
@@ -40,10 +68,6 @@ module GraphQL
|
|
40
68
|
true
|
41
69
|
end
|
42
70
|
|
43
|
-
def accessible?(ctx)
|
44
|
-
node_type.accessible?(ctx)
|
45
|
-
end
|
46
|
-
|
47
71
|
def visible?(ctx)
|
48
72
|
node_type.visible?(ctx)
|
49
73
|
end
|
@@ -52,11 +76,15 @@ module GraphQL
|
|
52
76
|
# Use `node_nullable(false)` in your base class to make non-null `node` field.
|
53
77
|
def node_nullable(new_value = nil)
|
54
78
|
if new_value.nil?
|
55
|
-
|
79
|
+
@node_nullable != nil ? @node_nullable : superclass.node_nullable
|
56
80
|
else
|
57
81
|
@node_nullable = new_value
|
58
82
|
end
|
59
83
|
end
|
84
|
+
|
85
|
+
protected
|
86
|
+
|
87
|
+
attr_writer :node_type, :node_nullable
|
60
88
|
end
|
61
89
|
end
|
62
90
|
end
|
@@ -5,13 +5,19 @@ module GraphQL
|
|
5
5
|
module Relay
|
6
6
|
module NodeBehaviors
|
7
7
|
def self.included(child_module)
|
8
|
-
child_module.extend(
|
8
|
+
child_module.extend(ClassMethods)
|
9
9
|
child_module.description("An object with an ID.")
|
10
10
|
child_module.field(:id, ID, null: false, description: "ID of the object.", resolver_method: :default_global_id)
|
11
11
|
end
|
12
12
|
|
13
13
|
def default_global_id
|
14
|
-
context.schema.id_from_object(object, self, context)
|
14
|
+
context.schema.id_from_object(object, self.class, context)
|
15
|
+
end
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
def default_relay?
|
19
|
+
true
|
20
|
+
end
|
15
21
|
end
|
16
22
|
end
|
17
23
|
end
|
@@ -4,8 +4,7 @@ module GraphQL
|
|
4
4
|
module Relay
|
5
5
|
module PageInfoBehaviors
|
6
6
|
def self.included(child_class)
|
7
|
-
child_class.extend
|
8
|
-
|
7
|
+
child_class.extend ClassMethods
|
9
8
|
child_class.description "Information about pagination in a connection."
|
10
9
|
child_class.field :has_next_page, Boolean, null: false,
|
11
10
|
description: "When paginating forwards, are there more items?"
|
@@ -20,6 +19,16 @@ module GraphQL
|
|
20
19
|
description: "When paginating forwards, the cursor to continue."
|
21
20
|
end
|
22
21
|
end
|
22
|
+
|
23
|
+
module ClassMethods
|
24
|
+
def default_relay?
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
28
|
+
def default_broadcastable?
|
29
|
+
true
|
30
|
+
end
|
31
|
+
end
|
23
32
|
end
|
24
33
|
end
|
25
34
|
end
|
data/lib/graphql/types/relay.rb
CHANGED
data/lib/graphql/types/string.rb
CHANGED
data/lib/graphql/types.rb
CHANGED
@@ -6,6 +6,7 @@ require "graphql/types/id"
|
|
6
6
|
require "graphql/types/int"
|
7
7
|
require "graphql/types/iso_8601_date"
|
8
8
|
require "graphql/types/iso_8601_date_time"
|
9
|
+
require "graphql/types/iso_8601_duration"
|
9
10
|
require "graphql/types/json"
|
10
11
|
require "graphql/types/string"
|
11
12
|
require "graphql/types/relay"
|
data/lib/graphql/version.rb
CHANGED