graphql 1.13.17 → 2.0.20
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_generator.rb +1 -1
- data/lib/generators/graphql/relay.rb +3 -17
- data/lib/generators/graphql/templates/schema.erb +3 -0
- data/lib/graphql/analysis/ast/field_usage.rb +3 -1
- data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -1
- data/lib/graphql/analysis/ast/query_complexity.rb +1 -1
- data/lib/graphql/analysis/ast/query_depth.rb +0 -1
- data/lib/graphql/analysis/ast/visitor.rb +43 -36
- data/lib/graphql/analysis/ast.rb +2 -12
- data/lib/graphql/analysis.rb +0 -7
- data/lib/graphql/backtrace/table.rb +2 -20
- data/lib/graphql/backtrace/tracer.rb +2 -3
- data/lib/graphql/backtrace.rb +2 -8
- data/lib/graphql/dataloader/null_dataloader.rb +3 -1
- data/lib/graphql/dataloader/source.rb +9 -0
- data/lib/graphql/dataloader.rb +4 -1
- data/lib/graphql/dig.rb +1 -1
- data/lib/graphql/execution/errors.rb +12 -82
- data/lib/graphql/execution/interpreter/resolve.rb +26 -0
- data/lib/graphql/execution/interpreter/runtime.rb +159 -120
- data/lib/graphql/execution/interpreter.rb +187 -78
- data/lib/graphql/execution/lazy.rb +7 -21
- data/lib/graphql/execution/lookahead.rb +44 -40
- data/lib/graphql/execution/multiplex.rb +3 -174
- data/lib/graphql/execution.rb +11 -4
- data/lib/graphql/introspection/directive_type.rb +2 -2
- data/lib/graphql/introspection/dynamic_fields.rb +3 -8
- data/lib/graphql/introspection/entry_points.rb +2 -15
- data/lib/graphql/introspection/field_type.rb +1 -1
- data/lib/graphql/introspection/schema_type.rb +2 -2
- data/lib/graphql/introspection/type_type.rb +13 -6
- data/lib/graphql/introspection.rb +4 -3
- data/lib/graphql/language/document_from_schema_definition.rb +18 -35
- data/lib/graphql/language/lexer.rb +216 -1488
- data/lib/graphql/language/nodes.rb +65 -39
- data/lib/graphql/language/parser.rb +376 -364
- data/lib/graphql/language/parser.y +49 -44
- data/lib/graphql/language/printer.rb +37 -21
- data/lib/graphql/language/visitor.rb +191 -83
- data/lib/graphql/pagination/active_record_relation_connection.rb +0 -8
- data/lib/graphql/pagination/array_connection.rb +4 -2
- data/lib/graphql/pagination/connection.rb +31 -4
- data/lib/graphql/pagination/connections.rb +3 -28
- data/lib/graphql/pagination/relation_connection.rb +2 -0
- data/lib/graphql/query/context.rb +155 -196
- data/lib/graphql/query/input_validation_result.rb +1 -1
- data/lib/graphql/query/null_context.rb +0 -3
- data/lib/graphql/query/validation_pipeline.rb +10 -34
- data/lib/graphql/query/variables.rb +7 -20
- data/lib/graphql/query.rb +32 -42
- data/lib/graphql/railtie.rb +0 -104
- data/lib/graphql/rake_task/validate.rb +1 -1
- data/lib/graphql/rake_task.rb +29 -1
- data/lib/graphql/relay/range_add.rb +9 -20
- data/lib/graphql/relay.rb +0 -15
- data/lib/graphql/schema/addition.rb +7 -9
- data/lib/graphql/schema/argument.rb +36 -43
- data/lib/graphql/schema/build_from_definition.rb +32 -18
- data/lib/graphql/schema/directive/one_of.rb +12 -0
- data/lib/graphql/schema/directive/transform.rb +1 -1
- data/lib/graphql/schema/directive.rb +12 -23
- data/lib/graphql/schema/enum.rb +28 -39
- data/lib/graphql/schema/enum_value.rb +5 -25
- data/lib/graphql/schema/field/connection_extension.rb +4 -0
- data/lib/graphql/schema/field.rb +237 -339
- data/lib/graphql/schema/input_object.rb +56 -67
- data/lib/graphql/schema/interface.rb +0 -35
- data/lib/graphql/schema/introspection_system.rb +3 -8
- data/lib/graphql/schema/late_bound_type.rb +8 -2
- data/lib/graphql/schema/list.rb +0 -6
- data/lib/graphql/schema/loader.rb +1 -2
- data/lib/graphql/schema/member/base_dsl_methods.rb +17 -19
- data/lib/graphql/schema/member/build_type.rb +5 -7
- data/lib/graphql/schema/member/has_arguments.rb +146 -55
- 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 -59
- data/lib/graphql/schema/member/has_fields.rb +17 -4
- data/lib/graphql/schema/member/has_interfaces.rb +49 -10
- data/lib/graphql/schema/member/has_validators.rb +31 -5
- data/lib/graphql/schema/member/relay_shortcuts.rb +47 -2
- data/lib/graphql/schema/member/type_system_helpers.rb +17 -0
- data/lib/graphql/schema/member/validates_input.rb +1 -1
- data/lib/graphql/schema/member.rb +0 -6
- data/lib/graphql/schema/mutation.rb +0 -9
- data/lib/graphql/schema/non_null.rb +1 -7
- data/lib/graphql/schema/object.rb +15 -52
- data/lib/graphql/schema/relay_classic_mutation.rb +53 -42
- data/lib/graphql/schema/resolver/has_payload_type.rb +20 -10
- data/lib/graphql/schema/resolver.rb +41 -42
- data/lib/graphql/schema/scalar.rb +7 -22
- data/lib/graphql/schema/subscription.rb +0 -7
- data/lib/graphql/schema/timeout.rb +24 -28
- data/lib/graphql/schema/type_membership.rb +3 -0
- data/lib/graphql/schema/union.rb +10 -17
- data/lib/graphql/schema/warden.rb +34 -8
- data/lib/graphql/schema/wrapper.rb +0 -5
- data/lib/graphql/schema.rb +241 -973
- data/lib/graphql/static_validation/all_rules.rb +1 -0
- data/lib/graphql/static_validation/base_visitor.rb +4 -21
- data/lib/graphql/static_validation/definition_dependencies.rb +7 -1
- data/lib/graphql/static_validation/error.rb +2 -2
- data/lib/graphql/static_validation/literal_validator.rb +19 -1
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +11 -5
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +12 -12
- 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/unique_directives_per_location.rb +12 -6
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +1 -1
- data/lib/graphql/static_validation/validator.rb +3 -25
- data/lib/graphql/static_validation.rb +0 -2
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +7 -1
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +38 -1
- data/lib/graphql/subscriptions/event.rb +3 -8
- data/lib/graphql/subscriptions/instrumentation.rb +0 -51
- data/lib/graphql/subscriptions.rb +32 -20
- data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
- data/lib/graphql/tracing/appoptics_trace.rb +231 -0
- data/lib/graphql/tracing/appsignal_trace.rb +71 -0
- data/lib/graphql/tracing/data_dog_trace.rb +148 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +2 -0
- data/lib/graphql/tracing/new_relic_trace.rb +75 -0
- data/lib/graphql/tracing/notifications_trace.rb +41 -0
- data/lib/graphql/tracing/platform_trace.rb +107 -0
- data/lib/graphql/tracing/platform_tracing.rb +26 -40
- 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/statsd_trace.rb +56 -0
- data/lib/graphql/tracing.rb +136 -40
- data/lib/graphql/type_kinds.rb +6 -3
- data/lib/graphql/types/iso_8601_date.rb +4 -1
- data/lib/graphql/types/iso_8601_date_time.rb +4 -0
- data/lib/graphql/types/relay/base_connection.rb +16 -6
- data/lib/graphql/types/relay/connection_behaviors.rb +29 -27
- data/lib/graphql/types/relay/edge_behaviors.rb +16 -5
- data/lib/graphql/types/relay/node_behaviors.rb +12 -2
- data/lib/graphql/types/relay/page_info_behaviors.rb +7 -2
- data/lib/graphql/types/relay.rb +0 -3
- data/lib/graphql/types/string.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +13 -74
- metadata +30 -133
- data/lib/graphql/analysis/analyze_query.rb +0 -98
- data/lib/graphql/analysis/field_usage.rb +0 -45
- data/lib/graphql/analysis/max_query_complexity.rb +0 -26
- data/lib/graphql/analysis/max_query_depth.rb +0 -26
- data/lib/graphql/analysis/query_complexity.rb +0 -88
- data/lib/graphql/analysis/query_depth.rb +0 -43
- data/lib/graphql/analysis/reducer_state.rb +0 -48
- data/lib/graphql/argument.rb +0 -131
- data/lib/graphql/authorization.rb +0 -82
- data/lib/graphql/backtrace/legacy_tracer.rb +0 -56
- data/lib/graphql/backwards_compatibility.rb +0 -61
- data/lib/graphql/base_type.rb +0 -232
- data/lib/graphql/boolean_type.rb +0 -2
- data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
- data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
- data/lib/graphql/compatibility/execution_specification.rb +0 -436
- data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
- data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -215
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -87
- data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
- data/lib/graphql/compatibility/query_parser_specification.rb +0 -266
- data/lib/graphql/compatibility/schema_parser_specification.rb +0 -682
- data/lib/graphql/compatibility.rb +0 -5
- data/lib/graphql/define/assign_argument.rb +0 -12
- data/lib/graphql/define/assign_connection.rb +0 -13
- data/lib/graphql/define/assign_enum_value.rb +0 -18
- data/lib/graphql/define/assign_global_id_field.rb +0 -11
- data/lib/graphql/define/assign_mutation_function.rb +0 -34
- data/lib/graphql/define/assign_object_field.rb +0 -42
- data/lib/graphql/define/defined_object_proxy.rb +0 -53
- data/lib/graphql/define/instance_definable.rb +0 -255
- data/lib/graphql/define/no_definition_error.rb +0 -7
- data/lib/graphql/define/non_null_with_bang.rb +0 -16
- data/lib/graphql/define/type_definer.rb +0 -31
- data/lib/graphql/define.rb +0 -31
- data/lib/graphql/deprecated_dsl.rb +0 -55
- data/lib/graphql/directive/deprecated_directive.rb +0 -2
- data/lib/graphql/directive/include_directive.rb +0 -2
- data/lib/graphql/directive/skip_directive.rb +0 -2
- data/lib/graphql/directive.rb +0 -107
- data/lib/graphql/enum_type.rb +0 -133
- data/lib/graphql/execution/execute.rb +0 -333
- data/lib/graphql/execution/flatten.rb +0 -40
- data/lib/graphql/execution/instrumentation.rb +0 -92
- data/lib/graphql/execution/lazy/resolve.rb +0 -91
- data/lib/graphql/execution/typecast.rb +0 -50
- data/lib/graphql/field/resolve.rb +0 -59
- data/lib/graphql/field.rb +0 -226
- data/lib/graphql/float_type.rb +0 -2
- data/lib/graphql/function.rb +0 -128
- data/lib/graphql/id_type.rb +0 -2
- data/lib/graphql/input_object_type.rb +0 -138
- data/lib/graphql/int_type.rb +0 -2
- data/lib/graphql/interface_type.rb +0 -72
- data/lib/graphql/internal_representation/document.rb +0 -27
- data/lib/graphql/internal_representation/node.rb +0 -206
- data/lib/graphql/internal_representation/print.rb +0 -51
- data/lib/graphql/internal_representation/rewrite.rb +0 -184
- data/lib/graphql/internal_representation/scope.rb +0 -88
- data/lib/graphql/internal_representation/visit.rb +0 -36
- data/lib/graphql/internal_representation.rb +0 -7
- data/lib/graphql/language/lexer.rl +0 -260
- data/lib/graphql/list_type.rb +0 -80
- data/lib/graphql/non_null_type.rb +0 -71
- data/lib/graphql/object_type.rb +0 -130
- data/lib/graphql/query/arguments.rb +0 -189
- data/lib/graphql/query/arguments_cache.rb +0 -24
- data/lib/graphql/query/executor.rb +0 -52
- data/lib/graphql/query/literal_input.rb +0 -136
- data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
- data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
- data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
- data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
- data/lib/graphql/query/serial_execution.rb +0 -40
- data/lib/graphql/relay/array_connection.rb +0 -83
- data/lib/graphql/relay/base_connection.rb +0 -189
- data/lib/graphql/relay/connection_instrumentation.rb +0 -54
- data/lib/graphql/relay/connection_resolve.rb +0 -43
- data/lib/graphql/relay/connection_type.rb +0 -54
- data/lib/graphql/relay/edge.rb +0 -27
- data/lib/graphql/relay/edge_type.rb +0 -19
- data/lib/graphql/relay/edges_instrumentation.rb +0 -39
- data/lib/graphql/relay/global_id_resolve.rb +0 -17
- data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
- data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
- data/lib/graphql/relay/mutation/resolve.rb +0 -56
- data/lib/graphql/relay/mutation/result.rb +0 -38
- data/lib/graphql/relay/mutation.rb +0 -106
- data/lib/graphql/relay/node.rb +0 -39
- data/lib/graphql/relay/page_info.rb +0 -7
- data/lib/graphql/relay/relation_connection.rb +0 -188
- data/lib/graphql/relay/type_extensions.rb +0 -32
- data/lib/graphql/scalar_type.rb +0 -91
- data/lib/graphql/schema/catchall_middleware.rb +0 -35
- data/lib/graphql/schema/default_parse_error.rb +0 -10
- data/lib/graphql/schema/default_type_error.rb +0 -17
- data/lib/graphql/schema/member/accepts_definition.rb +0 -164
- data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -58
- data/lib/graphql/schema/member/instrumentation.rb +0 -131
- data/lib/graphql/schema/middleware_chain.rb +0 -82
- data/lib/graphql/schema/possible_types.rb +0 -44
- data/lib/graphql/schema/rescue_middleware.rb +0 -60
- data/lib/graphql/schema/timeout_middleware.rb +0 -88
- data/lib/graphql/schema/traversal.rb +0 -228
- data/lib/graphql/schema/validation.rb +0 -313
- data/lib/graphql/static_validation/default_visitor.rb +0 -15
- data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
- data/lib/graphql/string_type.rb +0 -2
- data/lib/graphql/subscriptions/subscription_root.rb +0 -76
- data/lib/graphql/tracing/skylight_tracing.rb +0 -70
- data/lib/graphql/types/relay/default_relay.rb +0 -31
- data/lib/graphql/types/relay/node_field.rb +0 -24
- data/lib/graphql/types/relay/nodes_field.rb +0 -43
- data/lib/graphql/union_type.rb +0 -115
- data/lib/graphql/upgrader/member.rb +0 -937
- data/lib/graphql/upgrader/schema.rb +0 -38
data/lib/graphql/schema.rb
CHANGED
@@ -1,24 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require "graphql/schema/addition"
|
3
3
|
require "graphql/schema/base_64_encoder"
|
4
|
-
require "graphql/schema/catchall_middleware"
|
5
|
-
require "graphql/schema/default_parse_error"
|
6
|
-
require "graphql/schema/default_type_error"
|
7
4
|
require "graphql/schema/find_inherited_value"
|
8
5
|
require "graphql/schema/finder"
|
9
6
|
require "graphql/schema/invalid_type_error"
|
10
7
|
require "graphql/schema/introspection_system"
|
11
8
|
require "graphql/schema/late_bound_type"
|
12
|
-
require "graphql/schema/middleware_chain"
|
13
9
|
require "graphql/schema/null_mask"
|
14
|
-
require "graphql/schema/possible_types"
|
15
|
-
require "graphql/schema/rescue_middleware"
|
16
10
|
require "graphql/schema/timeout"
|
17
|
-
require "graphql/schema/timeout_middleware"
|
18
|
-
require "graphql/schema/traversal"
|
19
11
|
require "graphql/schema/type_expression"
|
20
12
|
require "graphql/schema/unique_within_type"
|
21
|
-
require "graphql/schema/validation"
|
22
13
|
require "graphql/schema/warden"
|
23
14
|
require "graphql/schema/build_from_definition"
|
24
15
|
|
@@ -40,6 +31,7 @@ require "graphql/schema/union"
|
|
40
31
|
require "graphql/schema/directive"
|
41
32
|
require "graphql/schema/directive/deprecated"
|
42
33
|
require "graphql/schema/directive/include"
|
34
|
+
require "graphql/schema/directive/one_of"
|
43
35
|
require "graphql/schema/directive/skip"
|
44
36
|
require "graphql/schema/directive/feature"
|
45
37
|
require "graphql/schema/directive/flagged"
|
@@ -70,7 +62,7 @@ module GraphQL
|
|
70
62
|
# Schemas can specify how queries should be executed against them.
|
71
63
|
# `query_execution_strategy`, `mutation_execution_strategy` and `subscription_execution_strategy`
|
72
64
|
# each apply to corresponding root types.
|
73
|
-
#
|
65
|
+
#
|
74
66
|
# @example defining a schema
|
75
67
|
# class MySchema < GraphQL::Schema
|
76
68
|
# query QueryType
|
@@ -79,21 +71,19 @@ module GraphQL
|
|
79
71
|
# end
|
80
72
|
#
|
81
73
|
class Schema
|
82
|
-
extend Forwardable
|
83
|
-
extend GraphQL::Schema::Member::AcceptsDefinition
|
84
74
|
extend GraphQL::Schema::Member::HasAstNode
|
85
|
-
include GraphQL::Define::InstanceDefinable
|
86
|
-
extend GraphQL::Define::InstanceDefinable::DeprecatedDefine
|
87
75
|
extend GraphQL::Schema::FindInheritedValue
|
88
76
|
|
89
|
-
class
|
90
|
-
|
91
|
-
|
77
|
+
class DuplicateNamesError < GraphQL::Error
|
78
|
+
attr_reader :duplicated_name
|
79
|
+
def initialize(duplicated_name:, duplicated_definition_1:, duplicated_definition_2:)
|
80
|
+
@duplicated_name = duplicated_name
|
81
|
+
super(
|
82
|
+
"Found two visible definitions for `#{duplicated_name}`: #{duplicated_definition_1}, #{duplicated_definition_2}"
|
83
|
+
)
|
92
84
|
end
|
93
85
|
end
|
94
86
|
|
95
|
-
class DuplicateNamesError < GraphQL::Error; end
|
96
|
-
|
97
87
|
class UnresolvedLateBoundTypeError < GraphQL::Error
|
98
88
|
attr_reader :type
|
99
89
|
def initialize(type:)
|
@@ -102,764 +92,70 @@ module GraphQL
|
|
102
92
|
end
|
103
93
|
end
|
104
94
|
|
105
|
-
|
106
|
-
|
107
|
-
# - Right away, if `value` is not registered with `lazy_resolve`
|
108
|
-
# - After resolving `value`, if it's registered with `lazy_resolve` (eg, `Promise`)
|
109
|
-
# @api private
|
110
|
-
def after_lazy(value, &block)
|
111
|
-
if lazy?(value)
|
112
|
-
GraphQL::Execution::Lazy.new do
|
113
|
-
result = sync_lazy(value)
|
114
|
-
# The returned result might also be lazy, so check it, too
|
115
|
-
after_lazy(result, &block)
|
116
|
-
end
|
117
|
-
else
|
118
|
-
yield(value) if block_given?
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
# Override this method to handle lazy objects in a custom way.
|
123
|
-
# @param value [Object] an instance of a class registered with {.lazy_resolve}
|
124
|
-
# @return [Object] A GraphQL-ready (non-lazy) object
|
125
|
-
# @api private
|
126
|
-
def sync_lazy(value)
|
127
|
-
lazy_method = lazy_method_name(value)
|
128
|
-
if lazy_method
|
129
|
-
synced_value = value.public_send(lazy_method)
|
130
|
-
sync_lazy(synced_value)
|
131
|
-
else
|
132
|
-
value
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
# @return [Symbol, nil] The method name to lazily resolve `obj`, or nil if `obj`'s class wasn't registered with {#lazy_resolve}.
|
137
|
-
def lazy_method_name(obj)
|
138
|
-
lazy_methods.get(obj)
|
139
|
-
end
|
140
|
-
|
141
|
-
# @return [Boolean] True if this object should be lazily resolved
|
142
|
-
def lazy?(obj)
|
143
|
-
!!lazy_method_name(obj)
|
144
|
-
end
|
145
|
-
|
146
|
-
# Return a lazy if any of `maybe_lazies` are lazy,
|
147
|
-
# otherwise, call the block eagerly and return the result.
|
148
|
-
# @param maybe_lazies [Array]
|
149
|
-
# @api private
|
150
|
-
def after_any_lazies(maybe_lazies)
|
151
|
-
if maybe_lazies.any? { |l| lazy?(l) }
|
152
|
-
GraphQL::Execution::Lazy.all(maybe_lazies).then do |result|
|
153
|
-
yield result
|
154
|
-
end
|
155
|
-
else
|
156
|
-
yield maybe_lazies
|
157
|
-
end
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
include LazyHandlingMethods
|
162
|
-
extend LazyHandlingMethods
|
163
|
-
|
164
|
-
deprecated_accepts_definitions \
|
165
|
-
:query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
|
166
|
-
:validate_timeout, :validate_max_errors, :max_depth, :max_complexity, :default_max_page_size,
|
167
|
-
:orphan_types, :resolve_type, :type_error, :parse_error,
|
168
|
-
:error_bubbling,
|
169
|
-
:raise_definition_error,
|
170
|
-
:object_from_id, :id_from_object,
|
171
|
-
:default_mask,
|
172
|
-
:cursor_encoder,
|
173
|
-
# If these are given as classes, normalize them. Accept `nil` when building from string.
|
174
|
-
query: ->(schema, t) { schema.query = t.respond_to?(:graphql_definition) ? t.graphql_definition : t },
|
175
|
-
mutation: ->(schema, t) { schema.mutation = t.respond_to?(:graphql_definition) ? t.graphql_definition : t },
|
176
|
-
subscription: ->(schema, t) { schema.subscription = t.respond_to?(:graphql_definition) ? t.graphql_definition : t },
|
177
|
-
disable_introspection_entry_points: ->(schema) { schema.disable_introspection_entry_points = true },
|
178
|
-
disable_schema_introspection_entry_point: ->(schema) { schema.disable_schema_introspection_entry_point = true },
|
179
|
-
disable_type_introspection_entry_point: ->(schema) { schema.disable_type_introspection_entry_point = true },
|
180
|
-
directives: ->(schema, directives) { schema.directives = directives.reduce({}) { |m, d| m[d.graphql_name] = d; m } },
|
181
|
-
directive: ->(schema, directive) { schema.directives[directive.graphql_name] = directive },
|
182
|
-
instrument: ->(schema, type, instrumenter, after_built_ins: false) {
|
183
|
-
if type == :field && after_built_ins
|
184
|
-
type = :field_after_built_ins
|
185
|
-
end
|
186
|
-
schema.instrumenters[type] << instrumenter
|
187
|
-
},
|
188
|
-
query_analyzer: ->(schema, analyzer) {
|
189
|
-
if analyzer == GraphQL::Authorization::Analyzer
|
190
|
-
GraphQL::Deprecation.warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
|
191
|
-
end
|
192
|
-
schema.query_analyzers << analyzer
|
193
|
-
},
|
194
|
-
multiplex_analyzer: ->(schema, analyzer) { schema.multiplex_analyzers << analyzer },
|
195
|
-
middleware: ->(schema, middleware) { schema.middleware << middleware },
|
196
|
-
lazy_resolve: ->(schema, lazy_class, lazy_value_method) { schema.lazy_methods.set(lazy_class, lazy_value_method) },
|
197
|
-
rescue_from: ->(schema, err_class, &block) { schema.rescue_from(err_class, &block) },
|
198
|
-
tracer: ->(schema, tracer) { schema.tracers.push(tracer) }
|
199
|
-
|
200
|
-
ensure_defined :introspection_system
|
201
|
-
|
202
|
-
attr_accessor \
|
203
|
-
:query, :mutation, :subscription,
|
204
|
-
:query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
|
205
|
-
:validate_timeout, :validate_max_errors, :max_depth, :max_complexity, :default_max_page_size,
|
206
|
-
:orphan_types, :directives,
|
207
|
-
:query_analyzers, :multiplex_analyzers, :instrumenters, :lazy_methods,
|
208
|
-
:cursor_encoder,
|
209
|
-
:ast_node,
|
210
|
-
:raise_definition_error,
|
211
|
-
:introspection_namespace,
|
212
|
-
:analysis_engine
|
213
|
-
|
214
|
-
# [Boolean] True if this object bubbles validation errors up from a field into its parent InputObject, if there is one.
|
215
|
-
attr_accessor :error_bubbling
|
216
|
-
|
217
|
-
# Single, long-lived instance of the provided subscriptions class, if there is one.
|
218
|
-
# @return [GraphQL::Subscriptions]
|
219
|
-
attr_accessor :subscriptions
|
220
|
-
|
221
|
-
# @return [MiddlewareChain] MiddlewareChain which is applied to fields during execution
|
222
|
-
attr_accessor :middleware
|
223
|
-
|
224
|
-
# @return [<#call(member, ctx)>] A callable for filtering members of the schema
|
225
|
-
# @see {Query.new} for query-specific filters with `except:`
|
226
|
-
attr_accessor :default_mask
|
227
|
-
|
228
|
-
# @see {GraphQL::Query::Context} The parent class of these classes
|
229
|
-
# @return [Class] Instantiated for each query
|
230
|
-
attr_accessor :context_class
|
231
|
-
|
232
|
-
# [Boolean] True if this object disables the introspection entry point fields
|
233
|
-
attr_accessor :disable_introspection_entry_points
|
234
|
-
|
235
|
-
def disable_introspection_entry_points?
|
236
|
-
!!@disable_introspection_entry_points
|
237
|
-
end
|
238
|
-
|
239
|
-
# [Boolean] True if this object disables the __schema introspection entry point field
|
240
|
-
attr_accessor :disable_schema_introspection_entry_point
|
241
|
-
|
242
|
-
def disable_schema_introspection_entry_point?
|
243
|
-
!!@disable_schema_introspection_entry_point
|
244
|
-
end
|
245
|
-
|
246
|
-
# [Boolean] True if this object disables the __type introspection entry point field
|
247
|
-
attr_accessor :disable_type_introspection_entry_point
|
248
|
-
|
249
|
-
def disable_type_introspection_entry_point?
|
250
|
-
!!@disable_type_introspection_entry_point
|
251
|
-
end
|
95
|
+
# Error that is raised when [#Schema#from_definition] is passed an invalid schema definition string.
|
96
|
+
class InvalidDocumentError < Error; end;
|
252
97
|
|
253
98
|
class << self
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
@static_validator = GraphQL::StaticValidation::Validator.new(schema: self)
|
278
|
-
@middleware = MiddlewareChain.new(final_step: GraphQL::Execution::Execute::FieldResolveStep)
|
279
|
-
@query_analyzers = []
|
280
|
-
@multiplex_analyzers = []
|
281
|
-
@resolve_type_proc = nil
|
282
|
-
@object_from_id_proc = nil
|
283
|
-
@id_from_object_proc = nil
|
284
|
-
@type_error_proc = DefaultTypeError
|
285
|
-
@parse_error_proc = DefaultParseError
|
286
|
-
@instrumenters = Hash.new { |h, k| h[k] = [] }
|
287
|
-
@lazy_methods = GraphQL::Execution::Lazy::LazyMethodMap.new
|
288
|
-
@lazy_methods.set(GraphQL::Execution::Lazy, :value)
|
289
|
-
@cursor_encoder = Base64Encoder
|
290
|
-
# For schema instances, default to legacy runtime modules
|
291
|
-
@analysis_engine = GraphQL::Analysis
|
292
|
-
@query_execution_strategy = GraphQL::Execution::Execute
|
293
|
-
@mutation_execution_strategy = GraphQL::Execution::Execute
|
294
|
-
@subscription_execution_strategy = GraphQL::Execution::Execute
|
295
|
-
@default_mask = GraphQL::Schema::NullMask
|
296
|
-
@rebuilding_artifacts = false
|
297
|
-
@context_class = GraphQL::Query::Context
|
298
|
-
@introspection_namespace = nil
|
299
|
-
@introspection_system = nil
|
300
|
-
@interpreter = false
|
301
|
-
@error_bubbling = false
|
302
|
-
@disable_introspection_entry_points = false
|
303
|
-
@disable_schema_introspection_entry_point = false
|
304
|
-
@disable_type_introspection_entry_point = false
|
305
|
-
end
|
306
|
-
|
307
|
-
# @return [Boolean] True if using the new {GraphQL::Execution::Interpreter}
|
308
|
-
def interpreter?
|
309
|
-
query_execution_strategy == GraphQL::Execution::Interpreter &&
|
310
|
-
mutation_execution_strategy == GraphQL::Execution::Interpreter &&
|
311
|
-
subscription_execution_strategy == GraphQL::Execution::Interpreter
|
312
|
-
end
|
313
|
-
|
314
|
-
def inspect
|
315
|
-
"#<#{self.class.name} ...>"
|
316
|
-
end
|
317
|
-
|
318
|
-
def initialize_copy(other)
|
319
|
-
super
|
320
|
-
@orphan_types = other.orphan_types.dup
|
321
|
-
@directives = other.directives.dup
|
322
|
-
@static_validator = GraphQL::StaticValidation::Validator.new(schema: self)
|
323
|
-
@middleware = other.middleware.dup
|
324
|
-
@query_analyzers = other.query_analyzers.dup
|
325
|
-
@multiplex_analyzers = other.multiplex_analyzers.dup
|
326
|
-
@tracers = other.tracers.dup
|
327
|
-
@possible_types = GraphQL::Schema::PossibleTypes.new(self)
|
328
|
-
|
329
|
-
@lazy_methods = other.lazy_methods.dup
|
330
|
-
|
331
|
-
@instrumenters = Hash.new { |h, k| h[k] = [] }
|
332
|
-
other.instrumenters.each do |key, insts|
|
333
|
-
@instrumenters[key].concat(insts)
|
334
|
-
end
|
335
|
-
|
336
|
-
if other.rescues?
|
337
|
-
@rescue_middleware = other.rescue_middleware
|
338
|
-
end
|
339
|
-
|
340
|
-
# This will be rebuilt when it's requested
|
341
|
-
# or during a later `define` call
|
342
|
-
@types = nil
|
343
|
-
@introspection_system = nil
|
344
|
-
end
|
345
|
-
|
346
|
-
def rescue_from(*args, &block)
|
347
|
-
rescue_middleware.rescue_from(*args, &block)
|
348
|
-
end
|
349
|
-
|
350
|
-
def remove_handler(*args, &block)
|
351
|
-
rescue_middleware.remove_handler(*args, &block)
|
352
|
-
end
|
353
|
-
|
354
|
-
def using_ast_analysis?
|
355
|
-
@analysis_engine == GraphQL::Analysis::AST
|
356
|
-
end
|
357
|
-
|
358
|
-
# For forwards-compatibility with Schema classes
|
359
|
-
alias :graphql_definition :itself
|
360
|
-
|
361
|
-
def deprecated_define(**kwargs, &block)
|
362
|
-
super
|
363
|
-
ensure_defined
|
364
|
-
# Assert that all necessary configs are present:
|
365
|
-
validation_error = Validation.validate(self)
|
366
|
-
validation_error && raise(GraphQL::RequiredImplementationMissingError, validation_error)
|
367
|
-
rebuild_artifacts
|
368
|
-
|
369
|
-
@definition_error = nil
|
370
|
-
nil
|
371
|
-
rescue StandardError => err
|
372
|
-
if @raise_definition_error || err.is_a?(CyclicalDefinitionError) || err.is_a?(GraphQL::RequiredImplementationMissingError)
|
373
|
-
raise
|
374
|
-
else
|
375
|
-
# Raise this error _later_ to avoid messing with Rails constant loading
|
376
|
-
@definition_error = err
|
377
|
-
end
|
378
|
-
nil
|
379
|
-
end
|
380
|
-
|
381
|
-
# Attach `instrumenter` to this schema for instrumenting events of `instrumentation_type`.
|
382
|
-
# @param instrumentation_type [Symbol]
|
383
|
-
# @param instrumenter
|
384
|
-
# @return [void]
|
385
|
-
def instrument(instrumentation_type, instrumenter)
|
386
|
-
@instrumenters[instrumentation_type] << instrumenter
|
387
|
-
if instrumentation_type == :field
|
388
|
-
rebuild_artifacts
|
389
|
-
end
|
390
|
-
end
|
391
|
-
|
392
|
-
# @return [Array<GraphQL::BaseType>] The root types of this schema
|
393
|
-
def root_types
|
394
|
-
@root_types ||= begin
|
395
|
-
rebuild_artifacts
|
396
|
-
@root_types
|
397
|
-
end
|
398
|
-
end
|
399
|
-
|
400
|
-
# @see [GraphQL::Schema::Warden] Restricted access to members of a schema
|
401
|
-
# @return [GraphQL::Schema::TypeMap] `{ name => type }` pairs of types in this schema
|
402
|
-
def types
|
403
|
-
@types ||= begin
|
404
|
-
rebuild_artifacts
|
405
|
-
@types
|
406
|
-
end
|
407
|
-
end
|
408
|
-
|
409
|
-
def get_type(type_name)
|
410
|
-
@types[type_name]
|
411
|
-
end
|
412
|
-
|
413
|
-
# @api private
|
414
|
-
def introspection_system
|
415
|
-
@introspection_system ||= begin
|
416
|
-
rebuild_artifacts
|
417
|
-
@introspection_system
|
418
|
-
end
|
419
|
-
end
|
420
|
-
|
421
|
-
# Returns a list of Arguments and Fields referencing a certain type
|
422
|
-
# @param type_name [String]
|
423
|
-
# @return [Hash]
|
424
|
-
def references_to(type_name = nil)
|
425
|
-
rebuild_artifacts unless defined?(@type_reference_map)
|
426
|
-
if type_name
|
427
|
-
@type_reference_map.fetch(type_name, [])
|
428
|
-
else
|
429
|
-
@type_reference_map
|
430
|
-
end
|
431
|
-
end
|
432
|
-
|
433
|
-
# Returns a list of Union types in which a type is a member
|
434
|
-
# @param type [GraphQL::ObjectType]
|
435
|
-
# @return [Array<GraphQL::UnionType>] list of union types of which the type is a member
|
436
|
-
def union_memberships(type)
|
437
|
-
rebuild_artifacts unless defined?(@union_memberships)
|
438
|
-
@union_memberships.fetch(type.name, [])
|
439
|
-
end
|
440
|
-
|
441
|
-
# Execute a query on itself. Raises an error if the schema definition is invalid.
|
442
|
-
# @see {Query#initialize} for arguments.
|
443
|
-
# @return [Hash] query result, ready to be serialized as JSON
|
444
|
-
def execute(query_str = nil, **kwargs)
|
445
|
-
if query_str
|
446
|
-
kwargs[:query] = query_str
|
447
|
-
end
|
448
|
-
# Some of the query context _should_ be passed to the multiplex, too
|
449
|
-
multiplex_context = if (ctx = kwargs[:context])
|
450
|
-
{
|
451
|
-
backtrace: ctx[:backtrace],
|
452
|
-
tracers: ctx[:tracers],
|
453
|
-
}
|
454
|
-
else
|
455
|
-
{}
|
456
|
-
end
|
457
|
-
# Since we're running one query, don't run a multiplex-level complexity analyzer
|
458
|
-
all_results = multiplex([kwargs], max_complexity: nil, context: multiplex_context)
|
459
|
-
all_results[0]
|
460
|
-
end
|
461
|
-
|
462
|
-
# Execute several queries on itself. Raises an error if the schema definition is invalid.
|
463
|
-
# @example Run several queries at once
|
464
|
-
# context = { ... }
|
465
|
-
# queries = [
|
466
|
-
# { query: params[:query_1], variables: params[:variables_1], context: context },
|
467
|
-
# { query: params[:query_2], variables: params[:variables_2], context: context },
|
468
|
-
# ]
|
469
|
-
# results = MySchema.multiplex(queries)
|
470
|
-
# render json: {
|
471
|
-
# result_1: results[0],
|
472
|
-
# result_2: results[1],
|
473
|
-
# }
|
474
|
-
#
|
475
|
-
# @see {Query#initialize} for query keyword arguments
|
476
|
-
# @see {Execution::Multiplex#run_queries} for multiplex keyword arguments
|
477
|
-
# @param queries [Array<Hash>] Keyword arguments for each query
|
478
|
-
# @param context [Hash] Multiplex-level context
|
479
|
-
# @return [Array<Hash>] One result for each query in the input
|
480
|
-
def multiplex(queries, **kwargs)
|
481
|
-
with_definition_error_check {
|
482
|
-
GraphQL::Execution::Multiplex.run_all(self, queries, **kwargs)
|
483
|
-
}
|
484
|
-
end
|
485
|
-
|
486
|
-
# Search for a schema member using a string path
|
487
|
-
# @example Finding a Field
|
488
|
-
# Schema.find("Ensemble.musicians")
|
489
|
-
#
|
490
|
-
# @see {GraphQL::Schema::Finder} for more examples
|
491
|
-
# @param path [String] A dot-separated path to the member
|
492
|
-
# @raise [Schema::Finder::MemberNotFoundError] if path could not be found
|
493
|
-
# @return [GraphQL::BaseType, GraphQL::Field, GraphQL::Argument, GraphQL::Directive] A GraphQL Schema Member
|
494
|
-
def find(path)
|
495
|
-
rebuild_artifacts unless defined?(@finder)
|
496
|
-
@find_cache[path] ||= @finder.find(path)
|
497
|
-
end
|
498
|
-
|
499
|
-
# Resolve field named `field_name` for type `parent_type`.
|
500
|
-
# Handles dynamic fields `__typename`, `__type` and `__schema`, too
|
501
|
-
# @param parent_type [String, GraphQL::BaseType]
|
502
|
-
# @param field_name [String]
|
503
|
-
# @return [GraphQL::Field, nil] The field named `field_name` on `parent_type`
|
504
|
-
# @see [GraphQL::Schema::Warden] Restricted access to members of a schema
|
505
|
-
def get_field(parent_type, field_name)
|
506
|
-
with_definition_error_check do
|
507
|
-
parent_type_name = case parent_type
|
508
|
-
when GraphQL::BaseType, Class, Module
|
509
|
-
parent_type.graphql_name
|
510
|
-
when String
|
511
|
-
parent_type
|
99
|
+
# Create schema with the result of an introspection query.
|
100
|
+
# @param introspection_result [Hash] A response from {GraphQL::Introspection::INTROSPECTION_QUERY}
|
101
|
+
# @return [Class<GraphQL::Schema>] the schema described by `input`
|
102
|
+
def from_introspection(introspection_result)
|
103
|
+
GraphQL::Schema::Loader.load(introspection_result)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Create schema from an IDL schema or file containing an IDL definition.
|
107
|
+
# @param definition_or_path [String] A schema definition string, or a path to a file containing the definition
|
108
|
+
# @param default_resolve [<#call(type, field, obj, args, ctx)>] A callable for handling field resolution
|
109
|
+
# @param parser [Object] An object for handling definition string parsing (must respond to `parse`)
|
110
|
+
# @param using [Hash] Plugins to attach to the created schema with `use(key, value)`
|
111
|
+
# @return [Class] the schema described by `document`
|
112
|
+
def from_definition(definition_or_path, default_resolve: nil, parser: GraphQL.default_parser, using: {})
|
113
|
+
# If the file ends in `.graphql` or `.graphqls`, treat it like a filepath
|
114
|
+
if definition_or_path.end_with?(".graphql") || definition_or_path.end_with?(".graphqls")
|
115
|
+
GraphQL::Schema::BuildFromDefinition.from_definition_path(
|
116
|
+
self,
|
117
|
+
definition_or_path,
|
118
|
+
default_resolve: default_resolve,
|
119
|
+
parser: parser,
|
120
|
+
using: using,
|
121
|
+
)
|
512
122
|
else
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
entry_point_field
|
521
|
-
elsif (dynamic_field = introspection_system.dynamic_field(name: field_name))
|
522
|
-
dynamic_field
|
523
|
-
else
|
524
|
-
nil
|
123
|
+
GraphQL::Schema::BuildFromDefinition.from_definition(
|
124
|
+
self,
|
125
|
+
definition_or_path,
|
126
|
+
default_resolve: default_resolve,
|
127
|
+
parser: parser,
|
128
|
+
using: using,
|
129
|
+
)
|
525
130
|
end
|
526
131
|
end
|
527
|
-
end
|
528
132
|
|
529
|
-
|
530
|
-
|
531
|
-
def get_fields(type)
|
532
|
-
@instrumented_field_map[type.graphql_name]
|
533
|
-
end
|
534
|
-
|
535
|
-
def type_from_ast(ast_node, context:)
|
536
|
-
GraphQL::Schema::TypeExpression.build_type(self, ast_node)
|
537
|
-
end
|
538
|
-
|
539
|
-
# @see [GraphQL::Schema::Warden] Restricted access to members of a schema
|
540
|
-
# @param type_defn [GraphQL::InterfaceType, GraphQL::UnionType] the type whose members you want to retrieve
|
541
|
-
# @param context [GraphQL::Query::Context] The context for the current query
|
542
|
-
# @return [Array<GraphQL::ObjectType>] types which belong to `type_defn` in this schema
|
543
|
-
def possible_types(type_defn, context = GraphQL::Query::NullContext)
|
544
|
-
if context == GraphQL::Query::NullContext
|
545
|
-
@possible_types ||= GraphQL::Schema::PossibleTypes.new(self)
|
546
|
-
@possible_types.possible_types(type_defn, context)
|
547
|
-
else
|
548
|
-
# Use the incoming context to cache this instance --
|
549
|
-
# if it were cached on the schema, we'd have a memory leak
|
550
|
-
# https://github.com/rmosolgo/graphql-ruby/issues/2878
|
551
|
-
ns = context.namespace(:possible_types)
|
552
|
-
per_query_possible_types = ns[:possible_types] ||= GraphQL::Schema::PossibleTypes.new(self)
|
553
|
-
per_query_possible_types.possible_types(type_defn, context)
|
554
|
-
end
|
555
|
-
end
|
556
|
-
|
557
|
-
# @see [GraphQL::Schema::Warden] Restricted access to root types
|
558
|
-
# @return [GraphQL::ObjectType, nil]
|
559
|
-
def root_type_for_operation(operation)
|
560
|
-
case operation
|
561
|
-
when "query"
|
562
|
-
query
|
563
|
-
when "mutation"
|
564
|
-
mutation
|
565
|
-
when "subscription"
|
566
|
-
subscription
|
567
|
-
else
|
568
|
-
raise ArgumentError, "unknown operation type: #{operation}"
|
569
|
-
end
|
570
|
-
end
|
571
|
-
|
572
|
-
def execution_strategy_for_operation(operation)
|
573
|
-
case operation
|
574
|
-
when "query"
|
575
|
-
query_execution_strategy
|
576
|
-
when "mutation"
|
577
|
-
mutation_execution_strategy
|
578
|
-
when "subscription"
|
579
|
-
subscription_execution_strategy
|
580
|
-
else
|
581
|
-
raise ArgumentError, "unknown operation type: #{operation}"
|
582
|
-
end
|
583
|
-
end
|
584
|
-
|
585
|
-
# Determine the GraphQL type for a given object.
|
586
|
-
# This is required for unions and interfaces (including Relay's `Node` interface)
|
587
|
-
# @see [GraphQL::Schema::Warden] Restricted access to members of a schema
|
588
|
-
# @param type [GraphQL::UnionType, GraphQL:InterfaceType] the abstract type which is being resolved
|
589
|
-
# @param object [Any] An application object which GraphQL is currently resolving on
|
590
|
-
# @param ctx [GraphQL::Query::Context] The context for the current query
|
591
|
-
# @return [GraphQL::ObjectType] The type for exposing `object` in GraphQL
|
592
|
-
def resolve_type(type, object, ctx = :__undefined__)
|
593
|
-
check_resolved_type(type, object, ctx) do |ok_type, ok_object, ok_ctx|
|
594
|
-
if @resolve_type_proc.nil?
|
595
|
-
raise(GraphQL::RequiredImplementationMissingError, "Can't determine GraphQL type for: #{ok_object.inspect}, define `resolve_type (type, obj, ctx) -> { ... }` inside `Schema.define`.")
|
596
|
-
end
|
597
|
-
@resolve_type_proc.call(ok_type, ok_object, ok_ctx)
|
598
|
-
end
|
599
|
-
end
|
600
|
-
|
601
|
-
# This is a compatibility hack so that instance-level and class-level
|
602
|
-
# methods can get correctness checks without calling one another
|
603
|
-
# @api private
|
604
|
-
def check_resolved_type(type, object, ctx = :__undefined__)
|
605
|
-
if ctx == :__undefined__
|
606
|
-
# Old method signature
|
607
|
-
ctx = object
|
608
|
-
object = type
|
609
|
-
type = nil
|
610
|
-
end
|
611
|
-
|
612
|
-
if object.is_a?(GraphQL::Schema::Object)
|
613
|
-
object = object.object
|
133
|
+
def deprecated_graphql_definition
|
134
|
+
graphql_definition(silence_deprecation_warning: true)
|
614
135
|
end
|
615
136
|
|
616
|
-
|
617
|
-
|
137
|
+
# @return [GraphQL::Subscriptions]
|
138
|
+
def subscriptions(inherited: true)
|
139
|
+
defined?(@subscriptions) ? @subscriptions : (inherited ? find_inherited_value(:subscriptions, nil) : nil)
|
618
140
|
end
|
619
141
|
|
620
|
-
|
621
|
-
|
622
|
-
type_result = if type_proc
|
623
|
-
type_proc.call(object, ctx)
|
624
|
-
else
|
625
|
-
yield(type, object, ctx)
|
142
|
+
def subscriptions=(new_implementation)
|
143
|
+
@subscriptions = new_implementation
|
626
144
|
end
|
627
145
|
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
if
|
633
|
-
|
634
|
-
end
|
635
|
-
if !resolved_type_result.is_a?(GraphQL::BaseType)
|
636
|
-
type_str = "#{resolved_type_result} (#{resolved_type_result.class.name})"
|
637
|
-
raise "resolve_type(#{object}) returned #{type_str}, but it should return a GraphQL type"
|
146
|
+
def trace_class(new_class = nil)
|
147
|
+
if new_class
|
148
|
+
@trace_class = new_class
|
149
|
+
elsif !defined?(@trace_class)
|
150
|
+
parent_trace_class = if superclass.respond_to?(:trace_class)
|
151
|
+
superclass.trace_class
|
638
152
|
else
|
639
|
-
|
153
|
+
GraphQL::Tracing::Trace
|
640
154
|
end
|
155
|
+
@trace_class = Class.new(parent_trace_class)
|
641
156
|
end
|
157
|
+
@trace_class
|
642
158
|
end
|
643
|
-
end
|
644
|
-
|
645
|
-
def resolve_type=(new_resolve_type_proc)
|
646
|
-
callable = GraphQL::BackwardsCompatibility.wrap_arity(new_resolve_type_proc, from: 2, to: 3, last: true, name: "Schema#resolve_type(type, obj, ctx)")
|
647
|
-
@resolve_type_proc = callable
|
648
|
-
end
|
649
|
-
|
650
|
-
# Fetch an application object by its unique id
|
651
|
-
# @param id [String] A unique identifier, provided previously by this GraphQL schema
|
652
|
-
# @param ctx [GraphQL::Query::Context] The context for the current query
|
653
|
-
# @return [Any] The application object identified by `id`
|
654
|
-
def object_from_id(id, ctx)
|
655
|
-
if @object_from_id_proc.nil?
|
656
|
-
raise(GraphQL::RequiredImplementationMissingError, "Can't fetch an object for id \"#{id}\" because the schema's `object_from_id (id, ctx) -> { ... }` function is not defined")
|
657
|
-
else
|
658
|
-
@object_from_id_proc.call(id, ctx)
|
659
|
-
end
|
660
|
-
end
|
661
|
-
|
662
|
-
# @param new_proc [#call] A new callable for fetching objects by ID
|
663
|
-
def object_from_id=(new_proc)
|
664
|
-
@object_from_id_proc = new_proc
|
665
|
-
end
|
666
|
-
|
667
|
-
# When we encounter a type error during query execution, we call this hook.
|
668
|
-
#
|
669
|
-
# You can use this hook to write a log entry,
|
670
|
-
# add a {GraphQL::ExecutionError} to the response (with `ctx.add_error`)
|
671
|
-
# or raise an exception and halt query execution.
|
672
|
-
#
|
673
|
-
# @example A `nil` is encountered by a non-null field
|
674
|
-
# type_error ->(err, query_ctx) {
|
675
|
-
# err.is_a?(GraphQL::InvalidNullError) # => true
|
676
|
-
# }
|
677
|
-
#
|
678
|
-
# @example An object doesn't resolve to one of a {UnionType}'s members
|
679
|
-
# type_error ->(err, query_ctx) {
|
680
|
-
# err.is_a?(GraphQL::UnresolvedTypeError) # => true
|
681
|
-
# }
|
682
|
-
#
|
683
|
-
# @see {DefaultTypeError} is the default behavior.
|
684
|
-
# @param err [GraphQL::TypeError] The error encountered during execution
|
685
|
-
# @param ctx [GraphQL::Query::Context] The context for the field where the error occurred
|
686
|
-
# @return void
|
687
|
-
def type_error(err, ctx)
|
688
|
-
@type_error_proc.call(err, ctx)
|
689
|
-
end
|
690
|
-
|
691
|
-
# @param new_proc [#call] A new callable for handling type errors during execution
|
692
|
-
def type_error=(new_proc)
|
693
|
-
@type_error_proc = new_proc
|
694
|
-
end
|
695
|
-
|
696
|
-
# Can't delegate to `class`
|
697
|
-
alias :_schema_class :class
|
698
|
-
def_delegators :_schema_class, :unauthorized_object, :unauthorized_field, :inaccessible_fields
|
699
|
-
def_delegators :_schema_class, :directive
|
700
|
-
def_delegators :_schema_class, :error_handler
|
701
|
-
def_delegators :_schema_class, :validate
|
702
|
-
|
703
|
-
|
704
|
-
# Given this schema member, find the class-based definition object
|
705
|
-
# whose `method_name` should be treated as an application hook
|
706
|
-
# @see {.visible?}
|
707
|
-
# @see {.accessible?}
|
708
|
-
def call_on_type_class(member, method_name, context, default:)
|
709
|
-
member = if member.respond_to?(:type_class)
|
710
|
-
member.type_class
|
711
|
-
else
|
712
|
-
member
|
713
|
-
end
|
714
|
-
|
715
|
-
if member.respond_to?(:relay_node_type) && (t = member.relay_node_type)
|
716
|
-
member = t
|
717
|
-
end
|
718
|
-
|
719
|
-
if member.respond_to?(method_name)
|
720
|
-
member.public_send(method_name, context)
|
721
|
-
else
|
722
|
-
default
|
723
|
-
end
|
724
|
-
end
|
725
|
-
|
726
|
-
def visible?(member, context)
|
727
|
-
call_on_type_class(member, :visible?, context, default: true)
|
728
|
-
end
|
729
|
-
|
730
|
-
def accessible?(member, context)
|
731
|
-
call_on_type_class(member, :accessible?, context, default: true)
|
732
|
-
end
|
733
|
-
|
734
|
-
# A function to call when {#execute} receives an invalid query string
|
735
|
-
#
|
736
|
-
# @see {DefaultParseError} is the default behavior.
|
737
|
-
# @param err [GraphQL::ParseError] The error encountered during parsing
|
738
|
-
# @param ctx [GraphQL::Query::Context] The context for the query where the error occurred
|
739
|
-
# @return void
|
740
|
-
def parse_error(err, ctx)
|
741
|
-
@parse_error_proc.call(err, ctx)
|
742
|
-
end
|
743
|
-
|
744
|
-
# @param new_proc [#call] A new callable for handling parse errors during execution
|
745
|
-
def parse_error=(new_proc)
|
746
|
-
@parse_error_proc = new_proc
|
747
|
-
end
|
748
|
-
|
749
|
-
# Get a unique identifier from this object
|
750
|
-
# @param object [Any] An application object
|
751
|
-
# @param type [GraphQL::BaseType] The current type definition
|
752
|
-
# @param ctx [GraphQL::Query::Context] the context for the current query
|
753
|
-
# @return [String] a unique identifier for `object` which clients can use to refetch it
|
754
|
-
def id_from_object(object, type, ctx)
|
755
|
-
if @id_from_object_proc.nil?
|
756
|
-
raise(GraphQL::RequiredImplementationMissingError, "Can't generate an ID for #{object.inspect} of type #{type}, schema's `id_from_object` must be defined")
|
757
|
-
else
|
758
|
-
@id_from_object_proc.call(object, type, ctx)
|
759
|
-
end
|
760
|
-
end
|
761
|
-
|
762
|
-
# @param new_proc [#call] A new callable for generating unique IDs
|
763
|
-
def id_from_object=(new_proc)
|
764
|
-
@id_from_object_proc = new_proc
|
765
|
-
end
|
766
|
-
|
767
|
-
# Create schema with the result of an introspection query.
|
768
|
-
# @param introspection_result [Hash] A response from {GraphQL::Introspection::INTROSPECTION_QUERY}
|
769
|
-
# @return [GraphQL::Schema] the schema described by `input`
|
770
|
-
def self.from_introspection(introspection_result)
|
771
|
-
GraphQL::Schema::Loader.load(introspection_result)
|
772
|
-
end
|
773
|
-
|
774
|
-
# Create schema from an IDL schema or file containing an IDL definition.
|
775
|
-
# @param definition_or_path [String] A schema definition string, or a path to a file containing the definition
|
776
|
-
# @param default_resolve [<#call(type, field, obj, args, ctx)>] A callable for handling field resolution
|
777
|
-
# @param parser [Object] An object for handling definition string parsing (must respond to `parse`)
|
778
|
-
# @param using [Hash] Plugins to attach to the created schema with `use(key, value)`
|
779
|
-
# @return [Class] the schema described by `document`
|
780
|
-
def self.from_definition(definition_or_path, default_resolve: nil, parser: GraphQL.default_parser, using: {})
|
781
|
-
# If the file ends in `.graphql`, treat it like a filepath
|
782
|
-
if definition_or_path.end_with?(".graphql")
|
783
|
-
GraphQL::Schema::BuildFromDefinition.from_definition_path(
|
784
|
-
definition_or_path,
|
785
|
-
default_resolve: default_resolve,
|
786
|
-
parser: parser,
|
787
|
-
using: using,
|
788
|
-
)
|
789
|
-
else
|
790
|
-
GraphQL::Schema::BuildFromDefinition.from_definition(
|
791
|
-
definition_or_path,
|
792
|
-
default_resolve: default_resolve,
|
793
|
-
parser: parser,
|
794
|
-
using: using,
|
795
|
-
)
|
796
|
-
end
|
797
|
-
end
|
798
|
-
|
799
|
-
# Error that is raised when [#Schema#from_definition] is passed an invalid schema definition string.
|
800
|
-
class InvalidDocumentError < Error; end;
|
801
|
-
|
802
|
-
# Return the GraphQL IDL for the schema
|
803
|
-
# @param context [Hash]
|
804
|
-
# @param only [<#call(member, ctx)>]
|
805
|
-
# @param except [<#call(member, ctx)>]
|
806
|
-
# @return [String]
|
807
|
-
def to_definition(only: nil, except: nil, context: {})
|
808
|
-
GraphQL::Schema::Printer.print_schema(self, only: only, except: except, context: context)
|
809
|
-
end
|
810
|
-
|
811
|
-
# Return the GraphQL::Language::Document IDL AST for the schema
|
812
|
-
# @param context [Hash]
|
813
|
-
# @param only [<#call(member, ctx)>]
|
814
|
-
# @param except [<#call(member, ctx)>]
|
815
|
-
# @return [GraphQL::Language::Document]
|
816
|
-
def to_document(only: nil, except: nil, context: {})
|
817
|
-
GraphQL::Language::DocumentFromSchemaDefinition.new(self, only: only, except: except, context: context).document
|
818
|
-
end
|
819
|
-
|
820
|
-
# Return the Hash response of {Introspection::INTROSPECTION_QUERY}.
|
821
|
-
# @param context [Hash]
|
822
|
-
# @param only [<#call(member, ctx)>]
|
823
|
-
# @param except [<#call(member, ctx)>]
|
824
|
-
# @return [Hash] GraphQL result
|
825
|
-
def as_json(only: nil, except: nil, context: {})
|
826
|
-
execute(Introspection.query(include_deprecated_args: true), only: only, except: except, context: context).to_h
|
827
|
-
end
|
828
|
-
|
829
|
-
# Returns the JSON response of {Introspection::INTROSPECTION_QUERY}.
|
830
|
-
# @see {#as_json}
|
831
|
-
# @return [String]
|
832
|
-
def to_json(*args)
|
833
|
-
JSON.pretty_generate(as_json(*args))
|
834
|
-
end
|
835
|
-
|
836
|
-
def new_connections?
|
837
|
-
!!connections
|
838
|
-
end
|
839
|
-
|
840
|
-
attr_accessor :connections
|
841
|
-
|
842
|
-
class << self
|
843
|
-
extend Forwardable
|
844
|
-
# For compatibility, these methods all:
|
845
|
-
# - Cause the Schema instance to be created, if it hasn't been created yet
|
846
|
-
# - Delegate to that instance
|
847
|
-
# Eventually, the methods will be moved into this class, removing the need for the singleton.
|
848
|
-
def_delegators :deprecated_graphql_definition,
|
849
|
-
# Execution
|
850
|
-
:execution_strategy_for_operation,
|
851
|
-
# Configuration
|
852
|
-
:metadata, :redefine,
|
853
|
-
:id_from_object_proc, :object_from_id_proc,
|
854
|
-
:id_from_object=, :object_from_id=,
|
855
|
-
:remove_handler
|
856
|
-
|
857
|
-
def deprecated_graphql_definition
|
858
|
-
graphql_definition(silence_deprecation_warning: true)
|
859
|
-
end
|
860
|
-
|
861
|
-
# @return [GraphQL::Subscriptions]
|
862
|
-
attr_accessor :subscriptions
|
863
159
|
|
864
160
|
# Returns the JSON response of {Introspection::INTROSPECTION_QUERY}.
|
865
161
|
# @see {#as_json}
|
@@ -872,9 +168,22 @@ module GraphQL
|
|
872
168
|
# @param context [Hash]
|
873
169
|
# @param only [<#call(member, ctx)>]
|
874
170
|
# @param except [<#call(member, ctx)>]
|
171
|
+
# @param include_deprecated_args [Boolean] If true, deprecated arguments will be included in the JSON response
|
172
|
+
# @param include_schema_description [Boolean] If true, the schema's description will be queried and included in the response
|
173
|
+
# @param include_is_repeatable [Boolean] If true, `isRepeatable: true|false` will be included with the schema's directives
|
174
|
+
# @param include_specified_by_url [Boolean] If true, scalar types' `specifiedByUrl:` will be included in the response
|
175
|
+
# @param include_is_one_of [Boolean] If true, `isOneOf: true|false` will be included with input objects
|
875
176
|
# @return [Hash] GraphQL result
|
876
|
-
def as_json(only: nil, except: nil, context: {})
|
877
|
-
|
177
|
+
def as_json(only: nil, except: nil, context: {}, include_deprecated_args: true, include_schema_description: false, include_is_repeatable: false, include_specified_by_url: false, include_is_one_of: false)
|
178
|
+
introspection_query = Introspection.query(
|
179
|
+
include_deprecated_args: include_deprecated_args,
|
180
|
+
include_schema_description: include_schema_description,
|
181
|
+
include_is_repeatable: include_is_repeatable,
|
182
|
+
include_is_one_of: include_is_one_of,
|
183
|
+
include_specified_by_url: include_specified_by_url,
|
184
|
+
)
|
185
|
+
|
186
|
+
execute(introspection_query, only: only, except: except, context: context).to_h
|
878
187
|
end
|
879
188
|
|
880
189
|
# Return the GraphQL IDL for the schema
|
@@ -911,17 +220,6 @@ module GraphQL
|
|
911
220
|
@find_cache[path] ||= @finder.find(path)
|
912
221
|
end
|
913
222
|
|
914
|
-
def graphql_definition(silence_deprecation_warning: false)
|
915
|
-
@graphql_definition ||= begin
|
916
|
-
unless silence_deprecation_warning
|
917
|
-
message = "Legacy `.graphql_definition` objects are deprecated and will be removed in GraphQL-Ruby 2.0. Use a class-based definition instead."
|
918
|
-
caller_message = "\n\nCalled on #{self.inspect} from:\n #{caller(1, 25).map { |l| " #{l}" }.join("\n")}"
|
919
|
-
GraphQL::Deprecation.warn(message + caller_message)
|
920
|
-
end
|
921
|
-
to_graphql(silence_deprecation_warning: silence_deprecation_warning)
|
922
|
-
end
|
923
|
-
end
|
924
|
-
|
925
223
|
def default_filter
|
926
224
|
GraphQL::Filter.new(except: default_mask)
|
927
225
|
end
|
@@ -951,73 +249,6 @@ module GraphQL
|
|
951
249
|
find_inherited_value(:plugins, EMPTY_ARRAY) + own_plugins
|
952
250
|
end
|
953
251
|
|
954
|
-
prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
|
955
|
-
def to_graphql
|
956
|
-
schema_defn = self.new
|
957
|
-
schema_defn.raise_definition_error = true
|
958
|
-
schema_defn.query = query && query.graphql_definition(silence_deprecation_warning: true)
|
959
|
-
schema_defn.mutation = mutation && mutation.graphql_definition(silence_deprecation_warning: true)
|
960
|
-
schema_defn.subscription = subscription && subscription.graphql_definition(silence_deprecation_warning: true)
|
961
|
-
schema_defn.validate_timeout = validate_timeout
|
962
|
-
schema_defn.validate_max_errors = validate_max_errors
|
963
|
-
schema_defn.max_complexity = max_complexity
|
964
|
-
schema_defn.error_bubbling = error_bubbling
|
965
|
-
schema_defn.max_depth = max_depth
|
966
|
-
schema_defn.default_max_page_size = default_max_page_size
|
967
|
-
schema_defn.orphan_types = orphan_types.map { |t| t.graphql_definition(silence_deprecation_warning: true) }
|
968
|
-
schema_defn.disable_introspection_entry_points = disable_introspection_entry_points?
|
969
|
-
schema_defn.disable_schema_introspection_entry_point = disable_schema_introspection_entry_point?
|
970
|
-
schema_defn.disable_type_introspection_entry_point = disable_type_introspection_entry_point?
|
971
|
-
|
972
|
-
prepped_dirs = {}
|
973
|
-
directives.each { |k, v| prepped_dirs[k] = v.graphql_definition}
|
974
|
-
schema_defn.directives = prepped_dirs
|
975
|
-
schema_defn.introspection_namespace = introspection
|
976
|
-
schema_defn.resolve_type = method(:resolve_type)
|
977
|
-
schema_defn.object_from_id = method(:object_from_id)
|
978
|
-
schema_defn.id_from_object = method(:id_from_object)
|
979
|
-
schema_defn.type_error = method(:type_error)
|
980
|
-
schema_defn.context_class = context_class
|
981
|
-
schema_defn.cursor_encoder = cursor_encoder
|
982
|
-
schema_defn.tracers.concat(tracers)
|
983
|
-
schema_defn.query_analyzers.concat(query_analyzers)
|
984
|
-
schema_defn.analysis_engine = analysis_engine
|
985
|
-
|
986
|
-
schema_defn.middleware.concat(all_middleware)
|
987
|
-
schema_defn.multiplex_analyzers.concat(multiplex_analyzers)
|
988
|
-
schema_defn.query_execution_strategy = query_execution_strategy
|
989
|
-
schema_defn.mutation_execution_strategy = mutation_execution_strategy
|
990
|
-
schema_defn.subscription_execution_strategy = subscription_execution_strategy
|
991
|
-
schema_defn.default_mask = default_mask
|
992
|
-
instrumenters.each do |step, insts|
|
993
|
-
insts.each do |inst|
|
994
|
-
schema_defn.instrumenters[step] << inst
|
995
|
-
end
|
996
|
-
end
|
997
|
-
|
998
|
-
lazy_methods.each do |lazy_class, value_method|
|
999
|
-
schema_defn.lazy_methods.set(lazy_class, value_method)
|
1000
|
-
end
|
1001
|
-
|
1002
|
-
error_handler.each_rescue do |err_class, handler|
|
1003
|
-
schema_defn.rescue_from(err_class, &handler)
|
1004
|
-
end
|
1005
|
-
|
1006
|
-
schema_defn.subscriptions ||= self.subscriptions
|
1007
|
-
|
1008
|
-
if !schema_defn.interpreter?
|
1009
|
-
schema_defn.instrumenters[:query] << GraphQL::Schema::Member::Instrumentation
|
1010
|
-
end
|
1011
|
-
|
1012
|
-
if new_connections?
|
1013
|
-
schema_defn.connections = self.connections
|
1014
|
-
end
|
1015
|
-
|
1016
|
-
schema_defn.send(:rebuild_artifacts)
|
1017
|
-
|
1018
|
-
schema_defn
|
1019
|
-
end
|
1020
|
-
|
1021
252
|
# Build a map of `{ name => type }` and return it
|
1022
253
|
# @return [Hash<String => Class>] A dictionary of type classes by their GraphQL name
|
1023
254
|
# @see get_type Which is more efficient for finding _one type_ by name, because it doesn't merge hashes.
|
@@ -1032,7 +263,9 @@ module GraphQL
|
|
1032
263
|
if visible_t.nil?
|
1033
264
|
visible_t = t
|
1034
265
|
else
|
1035
|
-
raise DuplicateNamesError
|
266
|
+
raise DuplicateNamesError.new(
|
267
|
+
duplicated_name: k, duplicated_definition_1: visible_t.inspect, duplicated_definition_2: t.inspect
|
268
|
+
)
|
1036
269
|
end
|
1037
270
|
end
|
1038
271
|
end
|
@@ -1059,7 +292,9 @@ module GraphQL
|
|
1059
292
|
if visible_t.nil?
|
1060
293
|
visible_t = t
|
1061
294
|
else
|
1062
|
-
raise DuplicateNamesError
|
295
|
+
raise DuplicateNamesError.new(
|
296
|
+
duplicated_name: type_name, duplicated_definition_1: visible_t.inspect, duplicated_definition_2: t.inspect
|
297
|
+
)
|
1063
298
|
end
|
1064
299
|
end
|
1065
300
|
end
|
@@ -1172,9 +407,7 @@ module GraphQL
|
|
1172
407
|
stored_possible_types = own_possible_types[type.graphql_name]
|
1173
408
|
visible_possible_types = if stored_possible_types && type.kind.interface?
|
1174
409
|
stored_possible_types.select do |possible_type|
|
1175
|
-
|
1176
|
-
# When we don't need to support legacy `.define` types, use `.include?(type)` instead.
|
1177
|
-
possible_type.interfaces(context).any? { |interface| interface.graphql_name == type.graphql_name }
|
410
|
+
possible_type.interfaces(context).include?(type)
|
1178
411
|
end
|
1179
412
|
else
|
1180
413
|
stored_possible_types
|
@@ -1309,6 +542,14 @@ module GraphQL
|
|
1309
542
|
end
|
1310
543
|
end
|
1311
544
|
|
545
|
+
def default_page_size(new_default_page_size = nil)
|
546
|
+
if new_default_page_size
|
547
|
+
@default_page_size = new_default_page_size
|
548
|
+
else
|
549
|
+
@default_page_size || find_inherited_value(:default_page_size)
|
550
|
+
end
|
551
|
+
end
|
552
|
+
|
1312
553
|
def query_execution_strategy(new_query_execution_strategy = nil)
|
1313
554
|
if new_query_execution_strategy
|
1314
555
|
@query_execution_strategy = new_query_execution_strategy
|
@@ -1393,13 +634,11 @@ module GraphQL
|
|
1393
634
|
end
|
1394
635
|
|
1395
636
|
def using_ast_analysis?
|
1396
|
-
|
637
|
+
true
|
1397
638
|
end
|
1398
639
|
|
1399
640
|
def interpreter?
|
1400
|
-
|
1401
|
-
mutation_execution_strategy == GraphQL::Execution::Interpreter &&
|
1402
|
-
subscription_execution_strategy == GraphQL::Execution::Interpreter
|
641
|
+
true
|
1403
642
|
end
|
1404
643
|
|
1405
644
|
attr_writer :interpreter
|
@@ -1504,26 +743,63 @@ module GraphQL
|
|
1504
743
|
|
1505
744
|
def rescue_from(*err_classes, &handler_block)
|
1506
745
|
err_classes.each do |err_class|
|
1507
|
-
|
746
|
+
Execution::Errors.register_rescue_from(err_class, error_handlers[:subclass_handlers], handler_block)
|
747
|
+
end
|
748
|
+
end
|
749
|
+
|
750
|
+
NEW_HANDLER_HASH = ->(h, k) {
|
751
|
+
h[k] = {
|
752
|
+
class: k,
|
753
|
+
handler: nil,
|
754
|
+
subclass_handlers: Hash.new(&NEW_HANDLER_HASH),
|
755
|
+
}
|
756
|
+
}
|
757
|
+
|
758
|
+
def error_handlers
|
759
|
+
@error_handlers ||= {
|
760
|
+
class: nil,
|
761
|
+
handler: nil,
|
762
|
+
subclass_handlers: Hash.new(&NEW_HANDLER_HASH),
|
763
|
+
}
|
764
|
+
end
|
765
|
+
|
766
|
+
# @api private
|
767
|
+
def handle_or_reraise(context, err)
|
768
|
+
handler = Execution::Errors.find_handler_for(self, err.class)
|
769
|
+
if handler
|
770
|
+
obj = context[:current_object]
|
771
|
+
args = context[:current_arguments]
|
772
|
+
args = args && args.respond_to?(:keyword_arguments) ? args.keyword_arguments : nil
|
773
|
+
field = context[:current_field]
|
774
|
+
if obj.is_a?(GraphQL::Schema::Object)
|
775
|
+
obj = obj.object
|
776
|
+
end
|
777
|
+
handler[:handler].call(err, obj, args, context, field)
|
778
|
+
else
|
779
|
+
raise err
|
1508
780
|
end
|
1509
781
|
end
|
1510
782
|
|
1511
783
|
# rubocop:disable Lint/DuplicateMethods
|
1512
784
|
module ResolveTypeWithType
|
1513
785
|
def resolve_type(type, obj, ctx)
|
1514
|
-
|
786
|
+
maybe_lazy_resolve_type_result = if type.is_a?(Module) && type.respond_to?(:resolve_type)
|
1515
787
|
type.resolve_type(obj, ctx)
|
1516
788
|
else
|
1517
789
|
super
|
1518
790
|
end
|
1519
791
|
|
1520
|
-
after_lazy(
|
1521
|
-
if
|
1522
|
-
|
1523
|
-
|
1524
|
-
|
1525
|
-
|
1526
|
-
|
792
|
+
after_lazy(maybe_lazy_resolve_type_result) do |resolve_type_result|
|
793
|
+
if resolve_type_result.is_a?(Array) && resolve_type_result.size == 2
|
794
|
+
resolved_type = resolve_type_result[0]
|
795
|
+
resolved_value = resolve_type_result[1]
|
796
|
+
else
|
797
|
+
resolved_type = resolve_type_result
|
798
|
+
resolved_value = obj
|
799
|
+
end
|
800
|
+
|
801
|
+
if resolved_type.nil? || (resolved_type.is_a?(Module) && resolved_type.respond_to?(:kind))
|
802
|
+
[resolved_type, resolved_value]
|
1527
803
|
else
|
1528
804
|
raise ".resolve_type should return a type definition, but got #{resolved_type.inspect} (#{resolved_type.class}) from `resolve_type(#{type}, #{obj}, #{ctx})`"
|
1529
805
|
end
|
@@ -1557,23 +833,16 @@ module GraphQL
|
|
1557
833
|
end
|
1558
834
|
|
1559
835
|
def visible?(member, ctx)
|
1560
|
-
member.
|
836
|
+
member.visible?(ctx)
|
1561
837
|
end
|
1562
838
|
|
1563
|
-
def
|
1564
|
-
|
839
|
+
def schema_directive(dir_class, **options)
|
840
|
+
@own_schema_directives ||= []
|
841
|
+
Member::HasDirectives.add_directive(self, @own_schema_directives, dir_class, options)
|
1565
842
|
end
|
1566
843
|
|
1567
|
-
|
1568
|
-
|
1569
|
-
#
|
1570
|
-
# By default, an error is added to the response. Override this hook to
|
1571
|
-
# track metrics or return a different error to the client.
|
1572
|
-
#
|
1573
|
-
# @param error [InaccessibleFieldsError] The analysis error for this check
|
1574
|
-
# @return [AnalysisError, nil] Return an error to skip the query
|
1575
|
-
def inaccessible_fields(error)
|
1576
|
-
error
|
844
|
+
def schema_directives
|
845
|
+
Member::HasDirectives.get_directives(self, @own_schema_directives, :schema_directives)
|
1577
846
|
end
|
1578
847
|
|
1579
848
|
# This hook is called when an object fails an `authorized?` check.
|
@@ -1611,41 +880,33 @@ module GraphQL
|
|
1611
880
|
unauthorized_object(unauthorized_error)
|
1612
881
|
end
|
1613
882
|
|
1614
|
-
def type_error(
|
1615
|
-
|
883
|
+
def type_error(type_error, ctx)
|
884
|
+
case type_error
|
885
|
+
when GraphQL::InvalidNullError
|
886
|
+
ctx.errors << type_error
|
887
|
+
when GraphQL::UnresolvedTypeError, GraphQL::StringEncodingError, GraphQL::IntegerEncodingError
|
888
|
+
raise type_error
|
889
|
+
when GraphQL::IntegerDecodingError
|
890
|
+
nil
|
891
|
+
end
|
1616
892
|
end
|
1617
893
|
|
1618
894
|
# A function to call when {#execute} receives an invalid query string
|
1619
895
|
#
|
1620
896
|
# The default is to add the error to `context.errors`
|
1621
|
-
# @param
|
897
|
+
# @param parse_err [GraphQL::ParseError] The error encountered during parsing
|
1622
898
|
# @param ctx [GraphQL::Query::Context] The context for the query where the error occurred
|
1623
899
|
# @return void
|
1624
900
|
def parse_error(parse_err, ctx)
|
1625
901
|
ctx.errors.push(parse_err)
|
1626
902
|
end
|
1627
903
|
|
1628
|
-
# @return [GraphQL::Execution::Errors]
|
1629
|
-
def error_handler
|
1630
|
-
@error_handler ||= GraphQL::Execution::Errors.new(self)
|
1631
|
-
end
|
1632
|
-
|
1633
904
|
def lazy_resolve(lazy_class, value_method)
|
1634
905
|
lazy_methods.set(lazy_class, value_method)
|
1635
906
|
end
|
1636
907
|
|
1637
908
|
def instrument(instrument_step, instrumenter, options = {})
|
1638
|
-
|
1639
|
-
GraphQL::Deprecation.warn "Field instrumentation (#{instrumenter.inspect}) will be removed in GraphQL-Ruby 2.0, please upgrade to field extensions: https://graphql-ruby.org/type_definitions/field_extensions.html"
|
1640
|
-
end
|
1641
|
-
|
1642
|
-
step = if instrument_step == :field && options[:after_built_ins]
|
1643
|
-
:field_after_built_ins
|
1644
|
-
else
|
1645
|
-
instrument_step
|
1646
|
-
end
|
1647
|
-
|
1648
|
-
own_instrumenters[step] << instrumenter
|
909
|
+
own_instrumenters[instrument_step] << instrumenter
|
1649
910
|
end
|
1650
911
|
|
1651
912
|
# Add several directives at once
|
@@ -1670,10 +931,17 @@ module GraphQL
|
|
1670
931
|
"include" => GraphQL::Schema::Directive::Include,
|
1671
932
|
"skip" => GraphQL::Schema::Directive::Skip,
|
1672
933
|
"deprecated" => GraphQL::Schema::Directive::Deprecated,
|
934
|
+
"oneOf" => GraphQL::Schema::Directive::OneOf,
|
1673
935
|
}.freeze
|
1674
936
|
end
|
1675
937
|
|
1676
938
|
def tracer(new_tracer)
|
939
|
+
if defined?(@trace_class) && !(@trace_class < GraphQL::Tracing::LegacyTrace)
|
940
|
+
raise ArgumentError, "Can't add tracer after configuring a `trace_class`, use GraphQL::Tracing::LegacyTrace to merge legacy tracers into a trace class instead."
|
941
|
+
elsif !defined?(@trace_class)
|
942
|
+
@trace_class = Class.new(GraphQL::Tracing::LegacyTrace)
|
943
|
+
end
|
944
|
+
|
1677
945
|
own_tracers << new_tracer
|
1678
946
|
end
|
1679
947
|
|
@@ -1681,10 +949,29 @@ module GraphQL
|
|
1681
949
|
find_inherited_value(:tracers, EMPTY_ARRAY) + own_tracers
|
1682
950
|
end
|
1683
951
|
|
1684
|
-
|
1685
|
-
|
1686
|
-
|
952
|
+
# Mix `trace_mod` into this schema's `Trace` class so that its methods
|
953
|
+
# will be called at runtime.
|
954
|
+
#
|
955
|
+
# @param trace_mod [Module] A module that implements tracing methods
|
956
|
+
# @param options [Hash] Keywords that will be passed to the tracing class during `#initialize`
|
957
|
+
# @return [void]
|
958
|
+
def trace_with(trace_mod, **options)
|
959
|
+
trace_options.merge!(options)
|
960
|
+
trace_class.include(trace_mod)
|
961
|
+
end
|
962
|
+
|
963
|
+
def trace_options
|
964
|
+
@trace_options ||= superclass.respond_to?(:trace_options) ? superclass.trace_options.dup : {}
|
965
|
+
end
|
966
|
+
|
967
|
+
def new_trace(**options)
|
968
|
+
if defined?(@trace_options)
|
969
|
+
options = trace_options.merge(options)
|
1687
970
|
end
|
971
|
+
trace_class.new(**options)
|
972
|
+
end
|
973
|
+
|
974
|
+
def query_analyzer(new_analyzer)
|
1688
975
|
own_query_analyzers << new_analyzer
|
1689
976
|
end
|
1690
977
|
|
@@ -1692,16 +979,6 @@ module GraphQL
|
|
1692
979
|
find_inherited_value(:query_analyzers, EMPTY_ARRAY) + own_query_analyzers
|
1693
980
|
end
|
1694
981
|
|
1695
|
-
def middleware(new_middleware = nil)
|
1696
|
-
if new_middleware
|
1697
|
-
GraphQL::Deprecation.warn "Middleware will be removed in GraphQL-Ruby 2.0, please upgrade to Field Extensions: https://graphql-ruby.org/type_definitions/field_extensions.html"
|
1698
|
-
own_middleware << new_middleware
|
1699
|
-
else
|
1700
|
-
# TODO make sure this is cached when running a query
|
1701
|
-
MiddlewareChain.new(steps: all_middleware, final_step: GraphQL::Execution::Execute::FieldResolveStep)
|
1702
|
-
end
|
1703
|
-
end
|
1704
|
-
|
1705
982
|
def multiplex_analyzer(new_analyzer)
|
1706
983
|
own_multiplex_analyzers << new_analyzer
|
1707
984
|
end
|
@@ -1755,17 +1032,12 @@ module GraphQL
|
|
1755
1032
|
# }
|
1756
1033
|
#
|
1757
1034
|
# @see {Query#initialize} for query keyword arguments
|
1758
|
-
# @see {Execution::Multiplex#
|
1035
|
+
# @see {Execution::Multiplex#run_all} for multiplex keyword arguments
|
1759
1036
|
# @param queries [Array<Hash>] Keyword arguments for each query
|
1760
1037
|
# @param context [Hash] Multiplex-level context
|
1761
1038
|
# @return [Array<Hash>] One result for each query in the input
|
1762
1039
|
def multiplex(queries, **kwargs)
|
1763
|
-
|
1764
|
-
self
|
1765
|
-
else
|
1766
|
-
graphql_definition
|
1767
|
-
end
|
1768
|
-
GraphQL::Execution::Multiplex.run_all(schema, queries, **kwargs)
|
1040
|
+
GraphQL::Execution::Interpreter.run_all(self, queries, **kwargs)
|
1769
1041
|
end
|
1770
1042
|
|
1771
1043
|
def instrumenters
|
@@ -1777,12 +1049,10 @@ module GraphQL
|
|
1777
1049
|
|
1778
1050
|
# @api private
|
1779
1051
|
def add_subscription_extension_if_necessary
|
1780
|
-
if
|
1052
|
+
if !defined?(@subscription_extension_added) && subscription && self.subscriptions
|
1781
1053
|
@subscription_extension_added = true
|
1782
|
-
|
1783
|
-
|
1784
|
-
else
|
1785
|
-
subscription.all_field_definitions.each do |field|
|
1054
|
+
subscription.all_field_definitions.each do |field|
|
1055
|
+
if !field.extensions.any? { |ext| ext.is_a?(Subscriptions::DefaultSubscriptionResolveExtension) }
|
1786
1056
|
field.extension(Subscriptions::DefaultSubscriptionResolveExtension)
|
1787
1057
|
end
|
1788
1058
|
end
|
@@ -1793,6 +1063,60 @@ module GraphQL
|
|
1793
1063
|
query.context.errors.push(GraphQL::ExecutionError.new("This query is too large to execute."))
|
1794
1064
|
end
|
1795
1065
|
|
1066
|
+
# Call the given block at the right time, either:
|
1067
|
+
# - Right away, if `value` is not registered with `lazy_resolve`
|
1068
|
+
# - After resolving `value`, if it's registered with `lazy_resolve` (eg, `Promise`)
|
1069
|
+
# @api private
|
1070
|
+
def after_lazy(value, &block)
|
1071
|
+
if lazy?(value)
|
1072
|
+
GraphQL::Execution::Lazy.new do
|
1073
|
+
result = sync_lazy(value)
|
1074
|
+
# The returned result might also be lazy, so check it, too
|
1075
|
+
after_lazy(result, &block)
|
1076
|
+
end
|
1077
|
+
else
|
1078
|
+
yield(value) if block_given?
|
1079
|
+
end
|
1080
|
+
end
|
1081
|
+
|
1082
|
+
# Override this method to handle lazy objects in a custom way.
|
1083
|
+
# @param value [Object] an instance of a class registered with {.lazy_resolve}
|
1084
|
+
# @return [Object] A GraphQL-ready (non-lazy) object
|
1085
|
+
# @api private
|
1086
|
+
def sync_lazy(value)
|
1087
|
+
lazy_method = lazy_method_name(value)
|
1088
|
+
if lazy_method
|
1089
|
+
synced_value = value.public_send(lazy_method)
|
1090
|
+
sync_lazy(synced_value)
|
1091
|
+
else
|
1092
|
+
value
|
1093
|
+
end
|
1094
|
+
end
|
1095
|
+
|
1096
|
+
# @return [Symbol, nil] The method name to lazily resolve `obj`, or nil if `obj`'s class wasn't registered with {#lazy_resolve}.
|
1097
|
+
def lazy_method_name(obj)
|
1098
|
+
lazy_methods.get(obj)
|
1099
|
+
end
|
1100
|
+
|
1101
|
+
# @return [Boolean] True if this object should be lazily resolved
|
1102
|
+
def lazy?(obj)
|
1103
|
+
!!lazy_method_name(obj)
|
1104
|
+
end
|
1105
|
+
|
1106
|
+
# Return a lazy if any of `maybe_lazies` are lazy,
|
1107
|
+
# otherwise, call the block eagerly and return the result.
|
1108
|
+
# @param maybe_lazies [Array]
|
1109
|
+
# @api private
|
1110
|
+
def after_any_lazies(maybe_lazies)
|
1111
|
+
if maybe_lazies.any? { |l| lazy?(l) }
|
1112
|
+
GraphQL::Execution::Lazy.all(maybe_lazies).then do |result|
|
1113
|
+
yield result
|
1114
|
+
end
|
1115
|
+
else
|
1116
|
+
yield maybe_lazies
|
1117
|
+
end
|
1118
|
+
end
|
1119
|
+
|
1796
1120
|
private
|
1797
1121
|
|
1798
1122
|
# @param t [Module, Array<Module>]
|
@@ -1902,68 +1226,12 @@ module GraphQL
|
|
1902
1226
|
@defined_query_analyzers ||= []
|
1903
1227
|
end
|
1904
1228
|
|
1905
|
-
def all_middleware
|
1906
|
-
find_inherited_value(:all_middleware, EMPTY_ARRAY) + own_middleware
|
1907
|
-
end
|
1908
|
-
|
1909
|
-
def own_middleware
|
1910
|
-
@own_middleware ||= []
|
1911
|
-
end
|
1912
|
-
|
1913
1229
|
def own_multiplex_analyzers
|
1914
1230
|
@own_multiplex_analyzers ||= []
|
1915
1231
|
end
|
1916
1232
|
end
|
1917
1233
|
|
1918
|
-
def dataloader_class
|
1919
|
-
self.class.dataloader_class
|
1920
|
-
end
|
1921
|
-
|
1922
1234
|
# Install these here so that subclasses will also install it.
|
1923
|
-
|
1924
|
-
|
1925
|
-
protected
|
1926
|
-
|
1927
|
-
def rescues?
|
1928
|
-
!!@rescue_middleware
|
1929
|
-
end
|
1930
|
-
|
1931
|
-
# Lazily create a middleware and add it to the schema
|
1932
|
-
# (Don't add it if it's not used)
|
1933
|
-
def rescue_middleware
|
1934
|
-
@rescue_middleware ||= GraphQL::Schema::RescueMiddleware.new.tap { |m| middleware.insert(0, m) }
|
1935
|
-
end
|
1936
|
-
|
1937
|
-
private
|
1938
|
-
|
1939
|
-
def rebuild_artifacts
|
1940
|
-
if @rebuilding_artifacts
|
1941
|
-
raise CyclicalDefinitionError, "Part of the schema build process re-triggered the schema build process, causing an infinite loop. Avoid using Schema#types, Schema#possible_types, and Schema#get_field during schema build."
|
1942
|
-
else
|
1943
|
-
@rebuilding_artifacts = true
|
1944
|
-
@introspection_system = Schema::IntrospectionSystem.new(self)
|
1945
|
-
traversal = Traversal.new(self)
|
1946
|
-
@types = traversal.type_map
|
1947
|
-
@root_types = [query, mutation, subscription]
|
1948
|
-
@instrumented_field_map = traversal.instrumented_field_map
|
1949
|
-
@type_reference_map = traversal.type_reference_map
|
1950
|
-
@union_memberships = traversal.union_memberships
|
1951
|
-
@find_cache = {}
|
1952
|
-
@finder = Finder.new(self)
|
1953
|
-
end
|
1954
|
-
ensure
|
1955
|
-
@rebuilding_artifacts = false
|
1956
|
-
end
|
1957
|
-
|
1958
|
-
class CyclicalDefinitionError < GraphQL::Error
|
1959
|
-
end
|
1960
|
-
|
1961
|
-
def with_definition_error_check
|
1962
|
-
if @definition_error
|
1963
|
-
raise @definition_error
|
1964
|
-
else
|
1965
|
-
yield
|
1966
|
-
end
|
1967
|
-
end
|
1235
|
+
self.connections = GraphQL::Pagination::Connections.new(schema: self)
|
1968
1236
|
end
|
1969
1237
|
end
|