graphql 2.4.5 → 2.5.21
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.
- checksums.yaml +4 -4
- data/lib/generators/graphql/detailed_trace_generator.rb +77 -0
- data/lib/generators/graphql/templates/create_graphql_detailed_traces.erb +10 -0
- data/lib/graphql/analysis/analyzer.rb +2 -1
- data/lib/graphql/analysis/query_complexity.rb +87 -7
- data/lib/graphql/analysis/visitor.rb +37 -40
- data/lib/graphql/analysis.rb +12 -9
- data/lib/graphql/autoload.rb +1 -0
- data/lib/graphql/backtrace/table.rb +118 -55
- data/lib/graphql/backtrace.rb +1 -19
- data/lib/graphql/current.rb +6 -1
- data/lib/graphql/dashboard/application_controller.rb +41 -0
- data/lib/graphql/dashboard/detailed_traces.rb +47 -0
- data/lib/graphql/dashboard/installable.rb +22 -0
- data/lib/graphql/dashboard/landings_controller.rb +9 -0
- data/lib/graphql/dashboard/limiters.rb +93 -0
- data/lib/graphql/dashboard/operation_store.rb +199 -0
- data/lib/graphql/dashboard/statics/bootstrap-5.3.3.min.css +6 -0
- data/lib/graphql/dashboard/statics/bootstrap-5.3.3.min.js +7 -0
- data/lib/graphql/dashboard/statics/charts.min.css +1 -0
- data/lib/graphql/dashboard/statics/dashboard.css +30 -0
- data/lib/graphql/dashboard/statics/dashboard.js +143 -0
- data/lib/graphql/dashboard/statics/header-icon.png +0 -0
- data/lib/graphql/dashboard/statics/icon.png +0 -0
- data/lib/graphql/dashboard/statics_controller.rb +31 -0
- data/lib/graphql/dashboard/subscriptions.rb +97 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/detailed_traces/traces/index.html.erb +45 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/landings/show.html.erb +18 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/limiters/limiters/show.html.erb +62 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/not_installed.html.erb +18 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/_form.html.erb +24 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/edit.html.erb +21 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/index.html.erb +69 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/new.html.erb +7 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/index.html.erb +39 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/show.html.erb +32 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/index.html.erb +81 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/show.html.erb +71 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/subscriptions/show.html.erb +41 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/index.html.erb +55 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/show.html.erb +40 -0
- data/lib/graphql/dashboard/views/layouts/graphql/dashboard/application.html.erb +108 -0
- data/lib/graphql/dashboard.rb +96 -0
- data/lib/graphql/dataloader/active_record_association_source.rb +84 -0
- data/lib/graphql/dataloader/active_record_source.rb +47 -0
- data/lib/graphql/dataloader/async_dataloader.rb +38 -15
- data/lib/graphql/dataloader/null_dataloader.rb +55 -10
- data/lib/graphql/dataloader/source.rb +18 -6
- data/lib/graphql/dataloader.rb +110 -26
- data/lib/graphql/date_encoding_error.rb +1 -1
- data/lib/graphql/dig.rb +2 -1
- data/lib/graphql/execution/interpreter/resolve.rb +10 -16
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +58 -5
- data/lib/graphql/execution/interpreter/runtime.rb +229 -93
- data/lib/graphql/execution/interpreter.rb +15 -24
- data/lib/graphql/execution/multiplex.rb +7 -6
- data/lib/graphql/execution/next/field_resolve_step.rb +690 -0
- data/lib/graphql/execution/next/load_argument_step.rb +60 -0
- data/lib/graphql/execution/next/prepare_object_step.rb +129 -0
- data/lib/graphql/execution/next/runner.rb +389 -0
- data/lib/graphql/execution/next/selections_step.rb +37 -0
- data/lib/graphql/execution/next.rb +69 -0
- data/lib/graphql/execution.rb +1 -0
- data/lib/graphql/execution_error.rb +13 -10
- data/lib/graphql/introspection/directive_location_enum.rb +1 -1
- data/lib/graphql/introspection/directive_type.rb +7 -3
- data/lib/graphql/introspection/dynamic_fields.rb +5 -1
- data/lib/graphql/introspection/entry_points.rb +11 -3
- data/lib/graphql/introspection/enum_value_type.rb +5 -5
- data/lib/graphql/introspection/field_type.rb +13 -5
- data/lib/graphql/introspection/input_value_type.rb +21 -13
- data/lib/graphql/introspection/type_type.rb +64 -28
- data/lib/graphql/invalid_name_error.rb +1 -1
- data/lib/graphql/invalid_null_error.rb +25 -16
- data/lib/graphql/language/document_from_schema_definition.rb +2 -1
- data/lib/graphql/language/lexer.rb +16 -5
- data/lib/graphql/language/nodes.rb +8 -1
- data/lib/graphql/language/parser.rb +16 -8
- data/lib/graphql/language/static_visitor.rb +37 -33
- data/lib/graphql/language/visitor.rb +59 -55
- data/lib/graphql/language.rb +21 -12
- data/lib/graphql/pagination/connection.rb +2 -0
- data/lib/graphql/pagination/connections.rb +32 -0
- data/lib/graphql/query/context.rb +6 -10
- data/lib/graphql/query/null_context.rb +9 -3
- data/lib/graphql/query/partial.rb +179 -0
- data/lib/graphql/query.rb +64 -64
- data/lib/graphql/railtie.rb +1 -1
- data/lib/graphql/schema/addition.rb +3 -1
- data/lib/graphql/schema/always_visible.rb +1 -0
- data/lib/graphql/schema/argument.rb +24 -8
- data/lib/graphql/schema/build_from_definition.rb +113 -54
- data/lib/graphql/schema/directive/flagged.rb +2 -0
- data/lib/graphql/schema/directive.rb +52 -2
- data/lib/graphql/schema/enum.rb +36 -1
- data/lib/graphql/schema/enum_value.rb +1 -1
- data/lib/graphql/schema/field/connection_extension.rb +15 -35
- data/lib/graphql/schema/field/scope_extension.rb +22 -13
- data/lib/graphql/schema/field.rb +101 -51
- data/lib/graphql/schema/field_extension.rb +33 -0
- data/lib/graphql/schema/input_object.rb +45 -38
- data/lib/graphql/schema/interface.rb +2 -1
- data/lib/graphql/schema/list.rb +1 -1
- data/lib/graphql/schema/member/base_dsl_methods.rb +1 -1
- data/lib/graphql/schema/member/has_arguments.rb +56 -19
- data/lib/graphql/schema/member/has_authorization.rb +35 -0
- data/lib/graphql/schema/member/has_dataloader.rb +79 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +15 -0
- data/lib/graphql/schema/member/has_directives.rb +1 -1
- data/lib/graphql/schema/member/has_fields.rb +81 -5
- data/lib/graphql/schema/member/has_interfaces.rb +3 -3
- data/lib/graphql/schema/member/scoped.rb +1 -1
- data/lib/graphql/schema/member/type_system_helpers.rb +17 -3
- data/lib/graphql/schema/member.rb +6 -0
- data/lib/graphql/schema/object.rb +18 -8
- data/lib/graphql/schema/ractor_shareable.rb +79 -0
- data/lib/graphql/schema/resolver.rb +52 -6
- data/lib/graphql/schema/scalar.rb +1 -6
- data/lib/graphql/schema/subscription.rb +50 -4
- data/lib/graphql/schema/timeout.rb +19 -2
- data/lib/graphql/schema/validator/required_validator.rb +71 -14
- data/lib/graphql/schema/visibility/migration.rb +3 -2
- data/lib/graphql/schema/visibility/profile.rb +115 -23
- data/lib/graphql/schema/visibility.rb +49 -32
- data/lib/graphql/schema/warden.rb +23 -2
- data/lib/graphql/schema.rb +333 -68
- data/lib/graphql/static_validation/all_rules.rb +2 -2
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +47 -13
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +79 -17
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +10 -2
- data/lib/graphql/static_validation/rules/not_single_subscription_error.rb +25 -0
- data/lib/graphql/static_validation/rules/subscription_root_exists_and_single_subscription_selection.rb +26 -0
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +6 -2
- data/lib/graphql/static_validation/validator.rb +6 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +1 -0
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +12 -10
- data/lib/graphql/subscriptions/event.rb +12 -1
- data/lib/graphql/subscriptions/serialize.rb +1 -1
- data/lib/graphql/subscriptions.rb +1 -1
- data/lib/graphql/testing/helpers.rb +17 -11
- data/lib/graphql/testing/mock_action_cable.rb +111 -0
- data/lib/graphql/testing.rb +1 -0
- data/lib/graphql/tracing/active_support_notifications_trace.rb +14 -3
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +1 -1
- data/lib/graphql/tracing/appoptics_trace.rb +9 -1
- data/lib/graphql/tracing/appoptics_tracing.rb +7 -0
- data/lib/graphql/tracing/appsignal_trace.rb +32 -55
- data/lib/graphql/tracing/appsignal_tracing.rb +2 -0
- data/lib/graphql/tracing/call_legacy_tracers.rb +66 -0
- data/lib/graphql/tracing/data_dog_trace.rb +46 -158
- data/lib/graphql/tracing/data_dog_tracing.rb +2 -0
- data/lib/graphql/tracing/detailed_trace/active_record_backend.rb +74 -0
- data/lib/graphql/tracing/detailed_trace/memory_backend.rb +60 -0
- data/lib/graphql/tracing/detailed_trace/redis_backend.rb +72 -0
- data/lib/graphql/tracing/detailed_trace.rb +156 -0
- data/lib/graphql/tracing/legacy_hooks_trace.rb +1 -0
- data/lib/graphql/tracing/legacy_trace.rb +4 -61
- data/lib/graphql/tracing/monitor_trace.rb +283 -0
- data/lib/graphql/tracing/new_relic_trace.rb +47 -54
- data/lib/graphql/tracing/new_relic_tracing.rb +2 -0
- data/lib/graphql/tracing/notifications_trace.rb +184 -34
- data/lib/graphql/tracing/notifications_tracing.rb +2 -0
- data/lib/graphql/tracing/null_trace.rb +9 -0
- data/lib/graphql/tracing/perfetto_trace/trace.proto +141 -0
- data/lib/graphql/tracing/perfetto_trace/trace_pb.rb +33 -0
- data/lib/graphql/tracing/perfetto_trace.rb +864 -0
- data/lib/graphql/tracing/platform_trace.rb +5 -0
- data/lib/graphql/tracing/prometheus_trace/graphql_collector.rb +2 -0
- data/lib/graphql/tracing/prometheus_trace.rb +72 -68
- data/lib/graphql/tracing/prometheus_tracing.rb +2 -0
- data/lib/graphql/tracing/scout_trace.rb +32 -55
- data/lib/graphql/tracing/scout_tracing.rb +2 -0
- data/lib/graphql/tracing/sentry_trace.rb +64 -94
- data/lib/graphql/tracing/statsd_trace.rb +33 -41
- data/lib/graphql/tracing/statsd_tracing.rb +2 -0
- data/lib/graphql/tracing/trace.rb +111 -1
- data/lib/graphql/tracing.rb +31 -30
- data/lib/graphql/type_kinds.rb +1 -0
- data/lib/graphql/types/relay/connection_behaviors.rb +9 -7
- data/lib/graphql/types/relay/edge_behaviors.rb +5 -4
- data/lib/graphql/types/relay/has_node_field.rb +13 -8
- data/lib/graphql/types/relay/has_nodes_field.rb +13 -8
- data/lib/graphql/types/relay/node_behaviors.rb +13 -2
- data/lib/graphql/unauthorized_error.rb +5 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +12 -31
- metadata +174 -11
- data/lib/graphql/backtrace/inspect_result.rb +0 -38
- data/lib/graphql/backtrace/trace.rb +0 -93
- data/lib/graphql/backtrace/tracer.rb +0 -80
- data/lib/graphql/schema/null_mask.rb +0 -11
- data/lib/graphql/static_validation/rules/subscription_root_exists.rb +0 -17
data/lib/graphql/query.rb
CHANGED
|
@@ -10,12 +10,47 @@ module GraphQL
|
|
|
10
10
|
autoload :Context, "graphql/query/context"
|
|
11
11
|
autoload :Fingerprint, "graphql/query/fingerprint"
|
|
12
12
|
autoload :NullContext, "graphql/query/null_context"
|
|
13
|
+
autoload :Partial, "graphql/query/partial"
|
|
13
14
|
autoload :Result, "graphql/query/result"
|
|
14
15
|
autoload :Variables, "graphql/query/variables"
|
|
15
16
|
autoload :InputValidationResult, "graphql/query/input_validation_result"
|
|
16
17
|
autoload :VariableValidationError, "graphql/query/variable_validation_error"
|
|
17
18
|
autoload :ValidationPipeline, "graphql/query/validation_pipeline"
|
|
18
19
|
|
|
20
|
+
# Code shared with {Partial}
|
|
21
|
+
module Runnable
|
|
22
|
+
def after_lazy(value, &block)
|
|
23
|
+
if !defined?(@runtime_instance)
|
|
24
|
+
@runtime_instance = context.namespace(:interpreter_runtime)[:runtime]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
if @runtime_instance
|
|
28
|
+
@runtime_instance.minimal_after_lazy(value, &block)
|
|
29
|
+
else
|
|
30
|
+
@schema.after_lazy(value, &block)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Node-level cache for calculating arguments. Used during execution and query analysis.
|
|
35
|
+
# @param ast_node [GraphQL::Language::Nodes::AbstractNode]
|
|
36
|
+
# @param definition [GraphQL::Schema::Field]
|
|
37
|
+
# @param parent_object [GraphQL::Schema::Object]
|
|
38
|
+
# @return [Hash{Symbol => Object}]
|
|
39
|
+
def arguments_for(ast_node, definition, parent_object: nil)
|
|
40
|
+
arguments_cache.fetch(ast_node, definition, parent_object)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def arguments_cache
|
|
44
|
+
@arguments_cache ||= Execution::Interpreter::ArgumentsCache.new(self)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# @api private
|
|
48
|
+
def handle_or_reraise(err)
|
|
49
|
+
@schema.handle_or_reraise(context, err)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
include Runnable
|
|
19
54
|
class OperationNameMissingError < GraphQL::ExecutionError
|
|
20
55
|
def initialize(name)
|
|
21
56
|
msg = if name.nil?
|
|
@@ -50,7 +85,7 @@ module GraphQL
|
|
|
50
85
|
# @return [GraphQL::StaticValidation::Validator] if present, the query will validate with these rules.
|
|
51
86
|
attr_reader :static_validator
|
|
52
87
|
|
|
53
|
-
# @param
|
|
88
|
+
# @param new_validator [GraphQL::StaticValidation::Validator] if present, the query will validate with these rules. This can't be reasssigned after validation.
|
|
54
89
|
def static_validator=(new_validator)
|
|
55
90
|
if defined?(@validation_pipeline) && @validation_pipeline && @validation_pipeline.has_validated?
|
|
56
91
|
raise ArgumentError, "Can't reassign Query#static_validator= after validation has run, remove this assignment."
|
|
@@ -97,21 +132,23 @@ module GraphQL
|
|
|
97
132
|
# @param root_value [Object] the object used to resolve fields on the root type
|
|
98
133
|
# @param max_depth [Numeric] the maximum number of nested selections allowed for this query (falls back to schema-level value)
|
|
99
134
|
# @param max_complexity [Numeric] the maximum field complexity for this query (falls back to schema-level value)
|
|
100
|
-
# @param visibility_profile [Symbol]
|
|
101
|
-
def initialize(schema, query_string = nil, query: nil, document: nil, context: nil, variables: nil, validate: true, static_validator: nil, visibility_profile: nil, subscription_topic: nil, operation_name: nil, root_value: nil, max_depth: schema.max_depth, max_complexity: schema.max_complexity, warden: nil, use_visibility_profile: nil)
|
|
135
|
+
# @param visibility_profile [Symbol] Another way to assign `context[:visibility_profile]`
|
|
136
|
+
def initialize(schema, query_string = nil, query: nil, document: nil, context: nil, variables: nil, multiplex: nil, validate: true, static_validator: nil, visibility_profile: nil, subscription_topic: nil, operation_name: nil, root_value: nil, max_depth: schema.max_depth, max_complexity: schema.max_complexity, warden: nil, use_visibility_profile: nil)
|
|
102
137
|
# Even if `variables: nil` is passed, use an empty hash for simpler logic
|
|
103
138
|
variables ||= {}
|
|
139
|
+
@multiplex = multiplex
|
|
104
140
|
@schema = schema
|
|
105
141
|
@context = schema.context_class.new(query: self, values: context)
|
|
142
|
+
if visibility_profile
|
|
143
|
+
@context[:visibility_profile] ||= visibility_profile
|
|
144
|
+
end
|
|
106
145
|
|
|
107
146
|
if use_visibility_profile.nil?
|
|
108
147
|
use_visibility_profile = warden ? false : schema.use_visibility_profile?
|
|
109
148
|
end
|
|
110
149
|
|
|
111
|
-
@visibility_profile = visibility_profile
|
|
112
|
-
|
|
113
150
|
if use_visibility_profile
|
|
114
|
-
@visibility_profile = @schema.visibility.profile_for(@context
|
|
151
|
+
@visibility_profile = @schema.visibility.profile_for(@context)
|
|
115
152
|
@warden = Schema::Warden::NullWarden.new(context: @context, schema: @schema)
|
|
116
153
|
else
|
|
117
154
|
@visibility_profile = nil
|
|
@@ -127,14 +164,6 @@ module GraphQL
|
|
|
127
164
|
context_tracers = (context ? context.fetch(:tracers, []) : [])
|
|
128
165
|
@tracers = schema.tracers + context_tracers
|
|
129
166
|
|
|
130
|
-
# Support `ctx[:backtrace] = true` for wrapping backtraces
|
|
131
|
-
if context && context[:backtrace] && !@tracers.include?(GraphQL::Backtrace::Tracer)
|
|
132
|
-
if schema.trace_class <= GraphQL::Tracing::CallLegacyTracers
|
|
133
|
-
context_tracers += [GraphQL::Backtrace::Tracer]
|
|
134
|
-
@tracers << GraphQL::Backtrace::Tracer
|
|
135
|
-
end
|
|
136
|
-
end
|
|
137
|
-
|
|
138
167
|
if !context_tracers.empty? && !(schema.trace_class <= GraphQL::Tracing::CallLegacyTracers)
|
|
139
168
|
raise ArgumentError, "context[:tracers] are not supported without `trace_with(GraphQL::Tracing::CallLegacyTracers)` in the schema configuration, please add it."
|
|
140
169
|
end
|
|
@@ -178,13 +207,7 @@ module GraphQL
|
|
|
178
207
|
@result_values = nil
|
|
179
208
|
@executed = false
|
|
180
209
|
|
|
181
|
-
@logger =
|
|
182
|
-
Logger.new(IO::NULL)
|
|
183
|
-
elsif context && (l = context[:logger])
|
|
184
|
-
l
|
|
185
|
-
else
|
|
186
|
-
schema.default_logger
|
|
187
|
-
end
|
|
210
|
+
@logger = schema.logger_for(context)
|
|
188
211
|
end
|
|
189
212
|
|
|
190
213
|
# If a document was provided to `GraphQL::Schema#execute` instead of the raw query string, we will need to get it from the document
|
|
@@ -210,19 +233,10 @@ module GraphQL
|
|
|
210
233
|
# @return [GraphQL::Execution::Lookahead]
|
|
211
234
|
def lookahead
|
|
212
235
|
@lookahead ||= begin
|
|
213
|
-
|
|
214
|
-
if ast_node.nil?
|
|
236
|
+
if selected_operation.nil?
|
|
215
237
|
GraphQL::Execution::Lookahead::NULL_LOOKAHEAD
|
|
216
238
|
else
|
|
217
|
-
root_type
|
|
218
|
-
when nil, "query"
|
|
219
|
-
types.query_root # rubocop:disable Development/ContextIsPassedCop
|
|
220
|
-
when "mutation"
|
|
221
|
-
types.mutation_root # rubocop:disable Development/ContextIsPassedCop
|
|
222
|
-
when "subscription"
|
|
223
|
-
types.subscription_root # rubocop:disable Development/ContextIsPassedCop
|
|
224
|
-
end
|
|
225
|
-
GraphQL::Execution::Lookahead.new(query: self, root_type: root_type, ast_nodes: [ast_node])
|
|
239
|
+
GraphQL::Execution::Lookahead.new(query: self, root_type: root_type, ast_nodes: [selected_operation])
|
|
226
240
|
end
|
|
227
241
|
end
|
|
228
242
|
end
|
|
@@ -248,6 +262,18 @@ module GraphQL
|
|
|
248
262
|
with_prepared_ast { @operations }
|
|
249
263
|
end
|
|
250
264
|
|
|
265
|
+
# Run subtree partials of this query and return their results.
|
|
266
|
+
# Each partial is identified with a `path:` and `object:`
|
|
267
|
+
# where the path references a field in the AST and the object will be treated
|
|
268
|
+
# as the return value from that field. Subfields of the field named by `path`
|
|
269
|
+
# will be executed with `object` as the starting point
|
|
270
|
+
# @param partials_hashes [Array<Hash{Symbol => Object}>] Hashes with `path:` and `object:` keys
|
|
271
|
+
# @return [Array<GraphQL::Query::Result>]
|
|
272
|
+
def run_partials(partials_hashes)
|
|
273
|
+
partials = partials_hashes.map { |partial_options| Partial.new(query: self, **partial_options) }
|
|
274
|
+
Execution::Interpreter.run_all(@schema, partials, context: @context)
|
|
275
|
+
end
|
|
276
|
+
|
|
251
277
|
# Get the result for this query, executing it once
|
|
252
278
|
# @return [GraphQL::Query::Result] A Hash-like GraphQL response, with `"data"` and/or `"errors"` keys
|
|
253
279
|
def result
|
|
@@ -290,19 +316,6 @@ module GraphQL
|
|
|
290
316
|
end
|
|
291
317
|
end
|
|
292
318
|
|
|
293
|
-
# Node-level cache for calculating arguments. Used during execution and query analysis.
|
|
294
|
-
# @param ast_node [GraphQL::Language::Nodes::AbstractNode]
|
|
295
|
-
# @param definition [GraphQL::Schema::Field]
|
|
296
|
-
# @param parent_object [GraphQL::Schema::Object]
|
|
297
|
-
# @return Hash{Symbol => Object}
|
|
298
|
-
def arguments_for(ast_node, definition, parent_object: nil)
|
|
299
|
-
arguments_cache.fetch(ast_node, definition, parent_object)
|
|
300
|
-
end
|
|
301
|
-
|
|
302
|
-
def arguments_cache
|
|
303
|
-
@arguments_cache ||= Execution::Interpreter::ArgumentsCache.new(self)
|
|
304
|
-
end
|
|
305
|
-
|
|
306
319
|
# A version of the given query string, with:
|
|
307
320
|
# - Variables inlined to the query
|
|
308
321
|
# - Strings replaced with `<REDACTED>`
|
|
@@ -369,17 +382,21 @@ module GraphQL
|
|
|
369
382
|
|
|
370
383
|
def root_type_for_operation(op_type)
|
|
371
384
|
case op_type
|
|
372
|
-
when "query"
|
|
385
|
+
when "query", nil
|
|
373
386
|
types.query_root # rubocop:disable Development/ContextIsPassedCop
|
|
374
387
|
when "mutation"
|
|
375
388
|
types.mutation_root # rubocop:disable Development/ContextIsPassedCop
|
|
376
389
|
when "subscription"
|
|
377
390
|
types.subscription_root # rubocop:disable Development/ContextIsPassedCop
|
|
378
391
|
else
|
|
379
|
-
raise ArgumentError, "unexpected root type name: #{op_type.inspect}; expected 'query', 'mutation', or 'subscription'"
|
|
392
|
+
raise ArgumentError, "unexpected root type name: #{op_type.inspect}; expected nil, 'query', 'mutation', or 'subscription'"
|
|
380
393
|
end
|
|
381
394
|
end
|
|
382
395
|
|
|
396
|
+
def root_type
|
|
397
|
+
root_type_for_operation(selected_operation.operation_type)
|
|
398
|
+
end
|
|
399
|
+
|
|
383
400
|
def types
|
|
384
401
|
@visibility_profile || warden.visibility_profile
|
|
385
402
|
end
|
|
@@ -412,23 +429,6 @@ module GraphQL
|
|
|
412
429
|
with_prepared_ast { @subscription }
|
|
413
430
|
end
|
|
414
431
|
|
|
415
|
-
# @api private
|
|
416
|
-
def handle_or_reraise(err)
|
|
417
|
-
schema.handle_or_reraise(context, err)
|
|
418
|
-
end
|
|
419
|
-
|
|
420
|
-
def after_lazy(value, &block)
|
|
421
|
-
if !defined?(@runtime_instance)
|
|
422
|
-
@runtime_instance = context.namespace(:interpreter_runtime)[:runtime]
|
|
423
|
-
end
|
|
424
|
-
|
|
425
|
-
if @runtime_instance
|
|
426
|
-
@runtime_instance.minimal_after_lazy(value, &block)
|
|
427
|
-
else
|
|
428
|
-
@schema.after_lazy(value, &block)
|
|
429
|
-
end
|
|
430
|
-
end
|
|
431
|
-
|
|
432
432
|
attr_reader :logger
|
|
433
433
|
|
|
434
434
|
private
|
data/lib/graphql/railtie.rb
CHANGED
|
@@ -258,7 +258,9 @@ module GraphQL
|
|
|
258
258
|
# We can get these now; we'll have to get late-bound types later
|
|
259
259
|
if interface_type.is_a?(Module) && type.is_a?(Class)
|
|
260
260
|
implementers = @possible_types[interface_type] ||= []
|
|
261
|
-
implementers
|
|
261
|
+
if !implementers.include?(type)
|
|
262
|
+
implementers << type
|
|
263
|
+
end
|
|
262
264
|
end
|
|
263
265
|
when String, Schema::LateBoundType
|
|
264
266
|
interface_type = interface_type_membership
|
|
@@ -4,6 +4,7 @@ module GraphQL
|
|
|
4
4
|
class Argument
|
|
5
5
|
include GraphQL::Schema::Member::HasPath
|
|
6
6
|
include GraphQL::Schema::Member::HasAstNode
|
|
7
|
+
include GraphQL::Schema::Member::HasAuthorization
|
|
7
8
|
include GraphQL::Schema::Member::HasDirectives
|
|
8
9
|
include GraphQL::Schema::Member::HasDeprecationReason
|
|
9
10
|
include GraphQL::Schema::Member::HasValidators
|
|
@@ -39,9 +40,14 @@ module GraphQL
|
|
|
39
40
|
# @param arg_name [Symbol]
|
|
40
41
|
# @param type_expr
|
|
41
42
|
# @param desc [String]
|
|
43
|
+
# @param type [Class, Array<Class>] Input type; positional argument also accepted
|
|
44
|
+
# @param name [Symbol] positional argument also accepted # @param loads [Class, Array<Class>] A GraphQL type to load for the given ID when one is present
|
|
45
|
+
# @param definition_block [Proc] Called with the newly-created {Argument}
|
|
46
|
+
# @param owner [Class] Private, used by GraphQL-Ruby during schema definition
|
|
42
47
|
# @param required [Boolean, :nullable] if true, this argument is non-null; if false, this argument is nullable. If `:nullable`, then the argument must be provided, though it may be `null`.
|
|
43
48
|
# @param description [String]
|
|
44
49
|
# @param default_value [Object]
|
|
50
|
+
# @param loads [Class, Array<Class>] A GraphQL type to load for the given ID when one is present
|
|
45
51
|
# @param as [Symbol] Override the keyword name when passed to a method
|
|
46
52
|
# @param prepare [Symbol] A method to call to transform this argument's valuebefore sending it to field resolution
|
|
47
53
|
# @param camelize [Boolean] if true, the name will be camelized when building the schema
|
|
@@ -50,9 +56,12 @@ module GraphQL
|
|
|
50
56
|
# @param deprecation_reason [String]
|
|
51
57
|
# @param validates [Hash, nil] Options for building validators, if any should be applied
|
|
52
58
|
# @param replace_null_with_default [Boolean] if `true`, incoming values of `null` will be replaced with the configured `default_value`
|
|
59
|
+
# @param comment [String] Private, used by GraphQL-Ruby when parsing GraphQL schema files
|
|
60
|
+
# @param ast_node [GraphQL::Language::Nodes::InputValueDefinition] Private, used by GraphQL-Ruby when parsing schema files
|
|
53
61
|
def initialize(arg_name = nil, type_expr = nil, desc = nil, required: true, type: nil, name: nil, loads: nil, description: nil, comment: nil, ast_node: nil, default_value: NOT_CONFIGURED, as: nil, from_resolver: false, camelize: true, prepare: nil, owner:, validates: nil, directives: nil, deprecation_reason: nil, replace_null_with_default: false, &definition_block)
|
|
54
62
|
arg_name ||= name
|
|
55
63
|
@name = -(camelize ? Member::BuildType.camelize(arg_name.to_s) : arg_name.to_s)
|
|
64
|
+
NameValidator.validate!(@name)
|
|
56
65
|
@type_expr = type_expr || type
|
|
57
66
|
@description = desc || description
|
|
58
67
|
@comment = comment
|
|
@@ -89,11 +98,8 @@ module GraphQL
|
|
|
89
98
|
end
|
|
90
99
|
|
|
91
100
|
if definition_block
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
else
|
|
95
|
-
instance_eval(&definition_block)
|
|
96
|
-
end
|
|
101
|
+
# `self` will still be self, it will also be the first argument to the block:
|
|
102
|
+
instance_exec(self, &definition_block)
|
|
97
103
|
end
|
|
98
104
|
end
|
|
99
105
|
|
|
@@ -159,6 +165,10 @@ module GraphQL
|
|
|
159
165
|
true
|
|
160
166
|
end
|
|
161
167
|
|
|
168
|
+
def authorizes?(_context)
|
|
169
|
+
self.method(:authorized?).owner != GraphQL::Schema::Argument
|
|
170
|
+
end
|
|
171
|
+
|
|
162
172
|
def authorized?(obj, value, ctx)
|
|
163
173
|
authorized_as_type?(obj, value, ctx, as_type: type)
|
|
164
174
|
end
|
|
@@ -214,12 +224,17 @@ module GraphQL
|
|
|
214
224
|
@statically_coercible = !requires_parent_object
|
|
215
225
|
end
|
|
216
226
|
|
|
227
|
+
def freeze
|
|
228
|
+
statically_coercible?
|
|
229
|
+
super
|
|
230
|
+
end
|
|
231
|
+
|
|
217
232
|
# Apply the {prepare} configuration to `value`, using methods from `obj`.
|
|
218
233
|
# Used by the runtime.
|
|
219
234
|
# @api private
|
|
220
235
|
def prepare_value(obj, value, context: nil)
|
|
221
236
|
if type.unwrap.kind.input_object?
|
|
222
|
-
value = recursively_prepare_input_object(value, type)
|
|
237
|
+
value = recursively_prepare_input_object(value, type, context)
|
|
223
238
|
end
|
|
224
239
|
|
|
225
240
|
Schema::Validator.validate!(validators, obj, context, value)
|
|
@@ -400,15 +415,16 @@ module GraphQL
|
|
|
400
415
|
|
|
401
416
|
private
|
|
402
417
|
|
|
403
|
-
def recursively_prepare_input_object(value, type)
|
|
418
|
+
def recursively_prepare_input_object(value, type, context)
|
|
404
419
|
if type.non_null?
|
|
405
420
|
type = type.of_type
|
|
406
421
|
end
|
|
407
422
|
|
|
408
423
|
if type.list? && !value.nil?
|
|
409
424
|
inner_type = type.of_type
|
|
410
|
-
value.map { |v| recursively_prepare_input_object(v, inner_type) }
|
|
425
|
+
value.map { |v| recursively_prepare_input_object(v, inner_type, context) }
|
|
411
426
|
elsif value.is_a?(GraphQL::Schema::InputObject)
|
|
427
|
+
value.validate_for(context)
|
|
412
428
|
value.prepare
|
|
413
429
|
else
|
|
414
430
|
value
|
|
@@ -20,8 +20,8 @@ module GraphQL
|
|
|
20
20
|
from_document(schema_superclass, parser.parse_file(definition_path), **kwargs)
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
def from_document(schema_superclass, document, default_resolve:, using: {}, relay: false)
|
|
24
|
-
Builder.build(schema_superclass, document, default_resolve: default_resolve || {}, relay: relay, using: using)
|
|
23
|
+
def from_document(schema_superclass, document, default_resolve:, using: {}, base_types: {}, relay: false)
|
|
24
|
+
Builder.build(schema_superclass, document, default_resolve: default_resolve || {}, relay: relay, using: using, base_types: base_types)
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
|
|
@@ -30,9 +30,18 @@ module GraphQL
|
|
|
30
30
|
include GraphQL::EmptyObjects
|
|
31
31
|
extend self
|
|
32
32
|
|
|
33
|
-
def build(schema_superclass, document, default_resolve:, using: {}, relay:)
|
|
33
|
+
def build(schema_superclass, document, default_resolve:, using: {}, base_types: {}, relay:)
|
|
34
34
|
raise InvalidDocumentError.new('Must provide a document ast.') if !document || !document.is_a?(GraphQL::Language::Nodes::Document)
|
|
35
35
|
|
|
36
|
+
base_types = {
|
|
37
|
+
object: GraphQL::Schema::Object,
|
|
38
|
+
interface: GraphQL::Schema::Interface,
|
|
39
|
+
union: GraphQL::Schema::Union,
|
|
40
|
+
scalar: GraphQL::Schema::Scalar,
|
|
41
|
+
enum: GraphQL::Schema::Enum,
|
|
42
|
+
input_object: GraphQL::Schema::InputObject,
|
|
43
|
+
}.merge!(base_types)
|
|
44
|
+
|
|
36
45
|
if default_resolve.is_a?(Hash)
|
|
37
46
|
default_resolve = ResolveMap.new(default_resolve)
|
|
38
47
|
end
|
|
@@ -53,7 +62,7 @@ module GraphQL
|
|
|
53
62
|
types[type_name] ||= begin
|
|
54
63
|
defn = document.definitions.find { |d| d.respond_to?(:name) && d.name == type_name }
|
|
55
64
|
if defn
|
|
56
|
-
build_definition_from_node(defn, directive_type_resolver, default_resolve)
|
|
65
|
+
build_definition_from_node(defn, directive_type_resolver, default_resolve, base_types)
|
|
57
66
|
elsif (built_in_defn = GraphQL::Schema::BUILT_IN_TYPES[type_name])
|
|
58
67
|
built_in_defn
|
|
59
68
|
else
|
|
@@ -77,14 +86,20 @@ module GraphQL
|
|
|
77
86
|
case definition
|
|
78
87
|
when GraphQL::Language::Nodes::SchemaDefinition, GraphQL::Language::Nodes::DirectiveDefinition
|
|
79
88
|
nil # already handled
|
|
80
|
-
when GraphQL::Language::Nodes::SchemaExtension
|
|
89
|
+
when GraphQL::Language::Nodes::SchemaExtension,
|
|
90
|
+
GraphQL::Language::Nodes::ScalarTypeExtension,
|
|
91
|
+
GraphQL::Language::Nodes::ObjectTypeExtension,
|
|
92
|
+
GraphQL::Language::Nodes::InterfaceTypeExtension,
|
|
93
|
+
GraphQL::Language::Nodes::UnionTypeExtension,
|
|
94
|
+
GraphQL::Language::Nodes::EnumTypeExtension,
|
|
95
|
+
GraphQL::Language::Nodes::InputObjectTypeExtension
|
|
81
96
|
schema_extensions ||= []
|
|
82
97
|
schema_extensions << definition
|
|
83
98
|
else
|
|
84
99
|
# It's possible that this was already loaded by the directives
|
|
85
100
|
prev_type = types[definition.name]
|
|
86
101
|
if prev_type.nil? || prev_type.is_a?(Schema::LateBoundType)
|
|
87
|
-
types[definition.name] = build_definition_from_node(definition, type_resolver, default_resolve)
|
|
102
|
+
types[definition.name] = build_definition_from_node(definition, type_resolver, default_resolve, base_types)
|
|
88
103
|
end
|
|
89
104
|
end
|
|
90
105
|
end
|
|
@@ -124,6 +139,34 @@ module GraphQL
|
|
|
124
139
|
|
|
125
140
|
raise InvalidDocumentError.new('Must provide schema definition with query type or a type named Query.') unless query_root_type
|
|
126
141
|
|
|
142
|
+
schema_extensions&.each do |ext|
|
|
143
|
+
next if ext.is_a?(GraphQL::Language::Nodes::SchemaExtension)
|
|
144
|
+
|
|
145
|
+
built_type = types[ext.name]
|
|
146
|
+
|
|
147
|
+
case ext
|
|
148
|
+
when GraphQL::Language::Nodes::ScalarTypeExtension
|
|
149
|
+
build_directives(built_type, ext, type_resolver)
|
|
150
|
+
when GraphQL::Language::Nodes::ObjectTypeExtension
|
|
151
|
+
build_directives(built_type, ext, type_resolver)
|
|
152
|
+
build_fields(built_type, ext.fields, type_resolver, default_resolve: true)
|
|
153
|
+
build_interfaces(built_type, ext.interfaces, type_resolver)
|
|
154
|
+
when GraphQL::Language::Nodes::InterfaceTypeExtension
|
|
155
|
+
build_directives(built_type, ext, type_resolver)
|
|
156
|
+
build_fields(built_type, ext.fields, type_resolver, default_resolve: nil)
|
|
157
|
+
build_interfaces(built_type, ext.interfaces, type_resolver)
|
|
158
|
+
when GraphQL::Language::Nodes::UnionTypeExtension
|
|
159
|
+
build_directives(built_type, ext, type_resolver)
|
|
160
|
+
built_type.possible_types(*ext.types.map { |type_name| type_resolver.call(type_name) })
|
|
161
|
+
when GraphQL::Language::Nodes::EnumTypeExtension
|
|
162
|
+
build_directives(built_type, ext, type_resolver)
|
|
163
|
+
build_values(built_type, ext.values, type_resolver)
|
|
164
|
+
when GraphQL::Language::Nodes::InputObjectTypeExtension
|
|
165
|
+
build_directives(built_type, ext, type_resolver)
|
|
166
|
+
build_arguments(built_type, ext.fields, type_resolver)
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
127
170
|
builder = self
|
|
128
171
|
|
|
129
172
|
found_types = types.values
|
|
@@ -144,6 +187,10 @@ module GraphQL
|
|
|
144
187
|
|
|
145
188
|
object_types.each do |t|
|
|
146
189
|
t.interfaces.each do |int_t|
|
|
190
|
+
if int_t.is_a?(LateBoundType)
|
|
191
|
+
int_t = types[int_t.graphql_name]
|
|
192
|
+
t.implements(int_t)
|
|
193
|
+
end
|
|
147
194
|
int_t.orphan_types(t)
|
|
148
195
|
end
|
|
149
196
|
end
|
|
@@ -192,8 +239,8 @@ module GraphQL
|
|
|
192
239
|
end
|
|
193
240
|
end
|
|
194
241
|
|
|
195
|
-
|
|
196
|
-
|
|
242
|
+
schema_extensions&.each do |ext|
|
|
243
|
+
if ext.is_a?(GraphQL::Language::Nodes::SchemaExtension)
|
|
197
244
|
build_directives(schema_class, ext, type_resolver)
|
|
198
245
|
end
|
|
199
246
|
end
|
|
@@ -205,20 +252,22 @@ module GraphQL
|
|
|
205
252
|
raise(GraphQL::RequiredImplementationMissingError, "Generated Schema cannot use Interface or Union types for execution. Implement resolve_type on your resolver.")
|
|
206
253
|
}
|
|
207
254
|
|
|
208
|
-
def build_definition_from_node(definition, type_resolver, default_resolve)
|
|
255
|
+
def build_definition_from_node(definition, type_resolver, default_resolve, base_types)
|
|
209
256
|
case definition
|
|
210
257
|
when GraphQL::Language::Nodes::EnumTypeDefinition
|
|
211
|
-
build_enum_type(definition, type_resolver)
|
|
258
|
+
build_enum_type(definition, type_resolver, base_types[:enum])
|
|
212
259
|
when GraphQL::Language::Nodes::ObjectTypeDefinition
|
|
213
|
-
build_object_type(definition, type_resolver)
|
|
260
|
+
build_object_type(definition, type_resolver, base_types[:object])
|
|
214
261
|
when GraphQL::Language::Nodes::InterfaceTypeDefinition
|
|
215
|
-
build_interface_type(definition, type_resolver)
|
|
262
|
+
build_interface_type(definition, type_resolver, base_types[:interface])
|
|
216
263
|
when GraphQL::Language::Nodes::UnionTypeDefinition
|
|
217
|
-
build_union_type(definition, type_resolver)
|
|
264
|
+
build_union_type(definition, type_resolver, base_types[:union])
|
|
218
265
|
when GraphQL::Language::Nodes::ScalarTypeDefinition
|
|
219
|
-
build_scalar_type(definition, type_resolver, default_resolve: default_resolve)
|
|
266
|
+
build_scalar_type(definition, type_resolver, base_types[:scalar], default_resolve: default_resolve)
|
|
220
267
|
when GraphQL::Language::Nodes::InputObjectTypeDefinition
|
|
221
|
-
build_input_object_type(definition, type_resolver)
|
|
268
|
+
build_input_object_type(definition, type_resolver, base_types[:input_object])
|
|
269
|
+
when GraphQL::Language::Nodes::DirectiveDefinition
|
|
270
|
+
build_directive(definition, type_resolver)
|
|
222
271
|
end
|
|
223
272
|
end
|
|
224
273
|
|
|
@@ -284,22 +333,26 @@ module GraphQL
|
|
|
284
333
|
end
|
|
285
334
|
end
|
|
286
335
|
|
|
287
|
-
def build_enum_type(enum_type_definition, type_resolver)
|
|
336
|
+
def build_enum_type(enum_type_definition, type_resolver, base_type)
|
|
288
337
|
builder = self
|
|
289
|
-
Class.new(
|
|
338
|
+
Class.new(base_type) do
|
|
290
339
|
graphql_name(enum_type_definition.name)
|
|
291
340
|
builder.build_directives(self, enum_type_definition, type_resolver)
|
|
292
341
|
description(enum_type_definition.description)
|
|
293
342
|
ast_node(enum_type_definition)
|
|
294
|
-
enum_type_definition.values
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
343
|
+
builder.build_values(self, enum_type_definition.values, type_resolver)
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def build_values(type_class, enum_value_definitions, type_resolver)
|
|
348
|
+
enum_value_definitions.each do |enum_value_definition|
|
|
349
|
+
type_class.value(enum_value_definition.name,
|
|
350
|
+
value: enum_value_definition.name,
|
|
351
|
+
deprecation_reason: build_deprecation_reason(enum_value_definition.directives),
|
|
352
|
+
description: enum_value_definition.description,
|
|
353
|
+
directives: prepare_directives(enum_value_definition, type_resolver),
|
|
354
|
+
ast_node: enum_value_definition,
|
|
355
|
+
)
|
|
303
356
|
end
|
|
304
357
|
end
|
|
305
358
|
|
|
@@ -313,9 +366,9 @@ module GraphQL
|
|
|
313
366
|
reason.value
|
|
314
367
|
end
|
|
315
368
|
|
|
316
|
-
def build_scalar_type(scalar_type_definition, type_resolver, default_resolve:)
|
|
369
|
+
def build_scalar_type(scalar_type_definition, type_resolver, base_type, default_resolve:)
|
|
317
370
|
builder = self
|
|
318
|
-
Class.new(
|
|
371
|
+
Class.new(base_type) do
|
|
319
372
|
graphql_name(scalar_type_definition.name)
|
|
320
373
|
description(scalar_type_definition.description)
|
|
321
374
|
ast_node(scalar_type_definition)
|
|
@@ -336,9 +389,9 @@ module GraphQL
|
|
|
336
389
|
end
|
|
337
390
|
end
|
|
338
391
|
|
|
339
|
-
def build_union_type(union_type_definition, type_resolver)
|
|
392
|
+
def build_union_type(union_type_definition, type_resolver, base_type)
|
|
340
393
|
builder = self
|
|
341
|
-
Class.new(
|
|
394
|
+
Class.new(base_type) do
|
|
342
395
|
graphql_name(union_type_definition.name)
|
|
343
396
|
description(union_type_definition.description)
|
|
344
397
|
possible_types(*union_type_definition.types.map { |type_name| type_resolver.call(type_name) })
|
|
@@ -347,27 +400,28 @@ module GraphQL
|
|
|
347
400
|
end
|
|
348
401
|
end
|
|
349
402
|
|
|
350
|
-
def build_object_type(object_type_definition, type_resolver)
|
|
403
|
+
def build_object_type(object_type_definition, type_resolver, base_type)
|
|
351
404
|
builder = self
|
|
352
405
|
|
|
353
|
-
Class.new(
|
|
406
|
+
Class.new(base_type) do
|
|
354
407
|
graphql_name(object_type_definition.name)
|
|
355
408
|
description(object_type_definition.description)
|
|
356
409
|
ast_node(object_type_definition)
|
|
357
410
|
builder.build_directives(self, object_type_definition, type_resolver)
|
|
358
|
-
|
|
359
|
-
object_type_definition.interfaces.each do |interface_name|
|
|
360
|
-
interface_defn = type_resolver.call(interface_name)
|
|
361
|
-
implements(interface_defn)
|
|
362
|
-
end
|
|
363
|
-
|
|
411
|
+
builder.build_interfaces(self, object_type_definition.interfaces, type_resolver)
|
|
364
412
|
builder.build_fields(self, object_type_definition.fields, type_resolver, default_resolve: true)
|
|
365
413
|
end
|
|
366
414
|
end
|
|
367
415
|
|
|
368
|
-
def
|
|
416
|
+
def build_interfaces(type_class, interface_names, type_resolver)
|
|
417
|
+
interface_names.each do |interface_name|
|
|
418
|
+
type_class.implements(type_resolver.call(interface_name))
|
|
419
|
+
end
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
def build_input_object_type(input_object_type_definition, type_resolver, base_type)
|
|
369
423
|
builder = self
|
|
370
|
-
Class.new(
|
|
424
|
+
Class.new(base_type) do
|
|
371
425
|
graphql_name(input_object_type_definition.name)
|
|
372
426
|
description(input_object_type_definition.description)
|
|
373
427
|
ast_node(input_object_type_definition)
|
|
@@ -427,16 +481,13 @@ module GraphQL
|
|
|
427
481
|
end
|
|
428
482
|
end
|
|
429
483
|
|
|
430
|
-
def build_interface_type(interface_type_definition, type_resolver)
|
|
484
|
+
def build_interface_type(interface_type_definition, type_resolver, base_type)
|
|
431
485
|
builder = self
|
|
432
486
|
Module.new do
|
|
433
|
-
include
|
|
487
|
+
include base_type
|
|
434
488
|
graphql_name(interface_type_definition.name)
|
|
435
489
|
description(interface_type_definition.description)
|
|
436
|
-
interface_type_definition.interfaces
|
|
437
|
-
interface_defn = type_resolver.call(interface_name)
|
|
438
|
-
implements(interface_defn)
|
|
439
|
-
end
|
|
490
|
+
builder.build_interfaces(self, interface_type_definition.interfaces, type_resolver)
|
|
440
491
|
ast_node(interface_type_definition)
|
|
441
492
|
builder.build_directives(self, interface_type_definition, type_resolver)
|
|
442
493
|
|
|
@@ -461,23 +512,31 @@ module GraphQL
|
|
|
461
512
|
camelize: false,
|
|
462
513
|
directives: prepare_directives(field_definition, type_resolver),
|
|
463
514
|
resolver_method: resolve_method_name,
|
|
515
|
+
resolve_batch: resolve_method_name,
|
|
464
516
|
)
|
|
465
517
|
|
|
466
518
|
builder.build_arguments(schema_field_defn, field_definition.arguments, type_resolver)
|
|
467
519
|
|
|
468
520
|
# Don't do this for interfaces
|
|
469
521
|
if default_resolve
|
|
470
|
-
owner
|
|
471
|
-
# frozen_string_literal: true
|
|
472
|
-
def #{resolve_method_name}(**args)
|
|
473
|
-
field_instance = self.class.get_field("#{field_definition.name}")
|
|
474
|
-
context.schema.definition_default_resolve.call(self.class, field_instance, object, args, context)
|
|
475
|
-
end
|
|
476
|
-
RUBY
|
|
522
|
+
define_field_resolve_method(owner, resolve_method_name, field_definition.name)
|
|
477
523
|
end
|
|
478
524
|
end
|
|
479
525
|
end
|
|
480
526
|
|
|
527
|
+
def define_field_resolve_method(owner, method_name, field_name)
|
|
528
|
+
owner.define_method(method_name) { |**args|
|
|
529
|
+
field_instance = context.types.field(owner, field_name)
|
|
530
|
+
context.schema.definition_default_resolve.call(self.class, field_instance, object, args, context)
|
|
531
|
+
}
|
|
532
|
+
owner.define_singleton_method(method_name) { |objects, context, **args|
|
|
533
|
+
field_instance = context.types.field(owner, field_name)
|
|
534
|
+
objects.map do |object|
|
|
535
|
+
context.schema.definition_default_resolve.call(self, field_instance, object, args, context)
|
|
536
|
+
end
|
|
537
|
+
}
|
|
538
|
+
end
|
|
539
|
+
|
|
481
540
|
def build_resolve_type(lookup_hash, directives, missing_type_handler)
|
|
482
541
|
resolve_type_proc = nil
|
|
483
542
|
resolve_type_proc = ->(ast_node) {
|
|
@@ -494,7 +553,7 @@ module GraphQL
|
|
|
494
553
|
when GraphQL::Language::Nodes::ListType
|
|
495
554
|
resolve_type_proc.call(ast_node.of_type).to_list_type
|
|
496
555
|
when String
|
|
497
|
-
directives[ast_node]
|
|
556
|
+
directives[ast_node] ||= missing_type_handler.call(ast_node)
|
|
498
557
|
else
|
|
499
558
|
raise "Unexpected ast_node: #{ast_node.inspect}"
|
|
500
559
|
end
|