graphql 2.0.13 → 2.3.10
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/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