graphql 2.2.17 → 2.5.16
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/install/mutation_root_generator.rb +2 -2
- data/lib/generators/graphql/install_generator.rb +46 -0
- data/lib/generators/graphql/orm_mutations_base.rb +1 -1
- data/lib/generators/graphql/templates/base_resolver.erb +2 -0
- data/lib/generators/graphql/templates/schema.erb +3 -0
- data/lib/generators/graphql/type_generator.rb +1 -1
- data/lib/graphql/analysis/analyzer.rb +90 -0
- data/lib/graphql/analysis/field_usage.rb +82 -0
- data/lib/graphql/analysis/max_query_complexity.rb +20 -0
- data/lib/graphql/analysis/max_query_depth.rb +20 -0
- data/lib/graphql/analysis/query_complexity.rb +263 -0
- data/lib/graphql/analysis/{ast/query_depth.rb → query_depth.rb} +23 -25
- data/lib/graphql/analysis/visitor.rb +280 -0
- data/lib/graphql/analysis.rb +95 -1
- data/lib/graphql/autoload.rb +38 -0
- data/lib/graphql/backtrace/table.rb +118 -55
- data/lib/graphql/backtrace.rb +1 -19
- data/lib/graphql/current.rb +57 -0
- data/lib/graphql/dashboard/detailed_traces.rb +47 -0
- data/lib/graphql/dashboard/installable.rb +22 -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/subscriptions.rb +96 -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 +23 -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 +158 -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 +46 -19
- data/lib/graphql/dataloader/null_dataloader.rb +51 -10
- data/lib/graphql/dataloader/source.rb +20 -9
- data/lib/graphql/dataloader.rb +153 -45
- data/lib/graphql/date_encoding_error.rb +1 -1
- data/lib/graphql/dig.rb +2 -1
- data/lib/graphql/execution/interpreter/argument_value.rb +5 -1
- data/lib/graphql/execution/interpreter/arguments_cache.rb +5 -10
- data/lib/graphql/execution/interpreter/resolve.rb +23 -25
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +63 -5
- data/lib/graphql/execution/interpreter/runtime.rb +321 -222
- data/lib/graphql/execution/interpreter.rb +23 -30
- data/lib/graphql/execution/lookahead.rb +18 -11
- data/lib/graphql/execution/multiplex.rb +6 -5
- data/lib/graphql/introspection/directive_location_enum.rb +1 -1
- data/lib/graphql/introspection/directive_type.rb +1 -1
- data/lib/graphql/introspection/entry_points.rb +2 -2
- data/lib/graphql/introspection/field_type.rb +1 -1
- data/lib/graphql/introspection/schema_type.rb +6 -11
- data/lib/graphql/introspection/type_type.rb +5 -5
- data/lib/graphql/invalid_name_error.rb +1 -1
- data/lib/graphql/invalid_null_error.rb +20 -17
- data/lib/graphql/language/cache.rb +13 -0
- data/lib/graphql/language/comment.rb +18 -0
- data/lib/graphql/language/document_from_schema_definition.rb +64 -35
- data/lib/graphql/language/lexer.rb +72 -42
- data/lib/graphql/language/nodes.rb +93 -52
- data/lib/graphql/language/parser.rb +168 -61
- data/lib/graphql/language/printer.rb +31 -15
- data/lib/graphql/language/sanitized_printer.rb +1 -1
- data/lib/graphql/language.rb +61 -1
- data/lib/graphql/pagination/connection.rb +1 -1
- data/lib/graphql/query/context/scoped_context.rb +1 -1
- data/lib/graphql/query/context.rb +46 -47
- data/lib/graphql/query/null_context.rb +3 -5
- data/lib/graphql/query/partial.rb +179 -0
- data/lib/graphql/query/validation_pipeline.rb +2 -2
- data/lib/graphql/query/variable_validation_error.rb +1 -1
- data/lib/graphql/query.rb +123 -69
- data/lib/graphql/railtie.rb +7 -0
- data/lib/graphql/rubocop/graphql/base_cop.rb +1 -1
- data/lib/graphql/rubocop/graphql/field_type_in_block.rb +144 -0
- data/lib/graphql/rubocop/graphql/root_types_in_block.rb +38 -0
- data/lib/graphql/rubocop.rb +2 -0
- data/lib/graphql/schema/addition.rb +26 -13
- data/lib/graphql/schema/always_visible.rb +7 -2
- data/lib/graphql/schema/argument.rb +57 -8
- data/lib/graphql/schema/build_from_definition.rb +116 -49
- data/lib/graphql/schema/directive/flagged.rb +4 -2
- data/lib/graphql/schema/directive.rb +54 -2
- data/lib/graphql/schema/enum.rb +107 -24
- data/lib/graphql/schema/enum_value.rb +10 -2
- data/lib/graphql/schema/field/connection_extension.rb +1 -1
- data/lib/graphql/schema/field/scope_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +134 -45
- data/lib/graphql/schema/field_extension.rb +1 -1
- data/lib/graphql/schema/has_single_input_argument.rb +6 -2
- data/lib/graphql/schema/input_object.rb +122 -64
- data/lib/graphql/schema/interface.rb +23 -5
- data/lib/graphql/schema/introspection_system.rb +6 -17
- data/lib/graphql/schema/late_bound_type.rb +4 -0
- data/lib/graphql/schema/list.rb +3 -3
- data/lib/graphql/schema/loader.rb +3 -2
- data/lib/graphql/schema/member/base_dsl_methods.rb +15 -0
- data/lib/graphql/schema/member/has_arguments.rb +44 -58
- data/lib/graphql/schema/member/has_dataloader.rb +62 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +15 -0
- data/lib/graphql/schema/member/has_directives.rb +4 -4
- data/lib/graphql/schema/member/has_fields.rb +26 -6
- data/lib/graphql/schema/member/has_interfaces.rb +6 -6
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +5 -1
- data/lib/graphql/schema/member/has_validators.rb +1 -1
- data/lib/graphql/schema/member/relay_shortcuts.rb +1 -1
- data/lib/graphql/schema/member/type_system_helpers.rb +17 -4
- data/lib/graphql/schema/member.rb +1 -0
- data/lib/graphql/schema/mutation.rb +7 -0
- data/lib/graphql/schema/object.rb +25 -8
- data/lib/graphql/schema/printer.rb +1 -0
- data/lib/graphql/schema/ractor_shareable.rb +79 -0
- data/lib/graphql/schema/relay_classic_mutation.rb +0 -1
- data/lib/graphql/schema/resolver.rb +29 -23
- data/lib/graphql/schema/scalar.rb +1 -6
- data/lib/graphql/schema/subscription.rb +52 -6
- data/lib/graphql/schema/timeout.rb +19 -2
- data/lib/graphql/schema/type_expression.rb +2 -2
- data/lib/graphql/schema/union.rb +1 -1
- data/lib/graphql/schema/validator/all_validator.rb +62 -0
- data/lib/graphql/schema/validator/required_validator.rb +92 -11
- data/lib/graphql/schema/validator.rb +3 -1
- data/lib/graphql/schema/visibility/migration.rb +188 -0
- data/lib/graphql/schema/visibility/profile.rb +445 -0
- data/lib/graphql/schema/visibility/visit.rb +190 -0
- data/lib/graphql/schema/visibility.rb +311 -0
- data/lib/graphql/schema/warden.rb +190 -20
- data/lib/graphql/schema.rb +695 -167
- data/lib/graphql/static_validation/all_rules.rb +2 -2
- data/lib/graphql/static_validation/base_visitor.rb +6 -5
- data/lib/graphql/static_validation/literal_validator.rb +4 -4
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
- data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +1 -1
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +3 -2
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +3 -3
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +2 -0
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +12 -2
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +47 -13
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +88 -25
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +10 -2
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +12 -2
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
- data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +1 -1
- data/lib/graphql/static_validation/rules/not_single_subscription_error.rb +25 -0
- data/lib/graphql/static_validation/rules/query_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -4
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +3 -3
- 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 +7 -3
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +18 -27
- data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +2 -2
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +11 -2
- data/lib/graphql/static_validation/validation_context.rb +18 -2
- data/lib/graphql/static_validation/validator.rb +6 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +5 -3
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +11 -5
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +12 -10
- data/lib/graphql/subscriptions/event.rb +13 -2
- data/lib/graphql/subscriptions/serialize.rb +1 -1
- data/lib/graphql/subscriptions.rb +7 -5
- data/lib/graphql/testing/helpers.rb +48 -16
- 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 +5 -1
- data/lib/graphql/tracing/appoptics_tracing.rb +7 -0
- data/lib/graphql/tracing/appsignal_trace.rb +32 -59
- 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 -162
- data/lib/graphql/tracing/data_dog_tracing.rb +2 -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 +141 -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 +183 -37
- 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 +818 -0
- data/lib/graphql/tracing/platform_tracing.rb +1 -1
- data/lib/graphql/tracing/prometheus_trace/graphql_collector.rb +2 -0
- data/lib/graphql/tracing/prometheus_trace.rb +73 -73
- data/lib/graphql/tracing/prometheus_tracing.rb +2 -0
- data/lib/graphql/tracing/scout_trace.rb +32 -58
- data/lib/graphql/tracing/scout_tracing.rb +2 -0
- data/lib/graphql/tracing/sentry_trace.rb +64 -98
- data/lib/graphql/tracing/statsd_trace.rb +33 -45
- 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 +2 -1
- data/lib/graphql/types/relay/connection_behaviors.rb +12 -2
- data/lib/graphql/types/relay/edge_behaviors.rb +11 -1
- data/lib/graphql/types/relay/page_info_behaviors.rb +4 -0
- data/lib/graphql/types.rb +18 -11
- data/lib/graphql/unauthorized_enum_value_error.rb +13 -0
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +64 -54
- metadata +197 -22
- data/lib/graphql/analysis/ast/analyzer.rb +0 -91
- data/lib/graphql/analysis/ast/field_usage.rb +0 -82
- data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -22
- data/lib/graphql/analysis/ast/max_query_depth.rb +0 -22
- data/lib/graphql/analysis/ast/query_complexity.rb +0 -182
- data/lib/graphql/analysis/ast/visitor.rb +0 -276
- data/lib/graphql/analysis/ast.rb +0 -94
- data/lib/graphql/backtrace/inspect_result.rb +0 -50
- data/lib/graphql/backtrace/trace.rb +0 -93
- data/lib/graphql/backtrace/tracer.rb +0 -80
- data/lib/graphql/language/token.rb +0 -34
- data/lib/graphql/schema/invalid_type_error.rb +0 -7
- 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
|
@@ -1,19 +1,56 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
require "graphql/query/context"
|
|
3
|
-
require "graphql/query/fingerprint"
|
|
4
|
-
require "graphql/query/null_context"
|
|
5
|
-
require "graphql/query/result"
|
|
6
|
-
require "graphql/query/variables"
|
|
7
|
-
require "graphql/query/input_validation_result"
|
|
8
|
-
require "graphql/query/variable_validation_error"
|
|
9
|
-
require "graphql/query/validation_pipeline"
|
|
10
2
|
|
|
11
3
|
module GraphQL
|
|
12
4
|
# A combination of query string and {Schema} instance which can be reduced to a {#result}.
|
|
13
5
|
class Query
|
|
6
|
+
extend Autoload
|
|
14
7
|
include Tracing::Traceable
|
|
15
8
|
extend Forwardable
|
|
16
9
|
|
|
10
|
+
autoload :Context, "graphql/query/context"
|
|
11
|
+
autoload :Fingerprint, "graphql/query/fingerprint"
|
|
12
|
+
autoload :NullContext, "graphql/query/null_context"
|
|
13
|
+
autoload :Partial, "graphql/query/partial"
|
|
14
|
+
autoload :Result, "graphql/query/result"
|
|
15
|
+
autoload :Variables, "graphql/query/variables"
|
|
16
|
+
autoload :InputValidationResult, "graphql/query/input_validation_result"
|
|
17
|
+
autoload :VariableValidationError, "graphql/query/variable_validation_error"
|
|
18
|
+
autoload :ValidationPipeline, "graphql/query/validation_pipeline"
|
|
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
|
|
17
54
|
class OperationNameMissingError < GraphQL::ExecutionError
|
|
18
55
|
def initialize(name)
|
|
19
56
|
msg = if name.nil?
|
|
@@ -48,7 +85,7 @@ module GraphQL
|
|
|
48
85
|
# @return [GraphQL::StaticValidation::Validator] if present, the query will validate with these rules.
|
|
49
86
|
attr_reader :static_validator
|
|
50
87
|
|
|
51
|
-
# @param
|
|
88
|
+
# @param new_validator [GraphQL::StaticValidation::Validator] if present, the query will validate with these rules. This can't be reasssigned after validation.
|
|
52
89
|
def static_validator=(new_validator)
|
|
53
90
|
if defined?(@validation_pipeline) && @validation_pipeline && @validation_pipeline.has_validated?
|
|
54
91
|
raise ArgumentError, "Can't reassign Query#static_validator= after validation has run, remove this assignment."
|
|
@@ -95,12 +132,29 @@ module GraphQL
|
|
|
95
132
|
# @param root_value [Object] the object used to resolve fields on the root type
|
|
96
133
|
# @param max_depth [Numeric] the maximum number of nested selections allowed for this query (falls back to schema-level value)
|
|
97
134
|
# @param max_complexity [Numeric] the maximum field complexity for this query (falls back to schema-level value)
|
|
98
|
-
|
|
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)
|
|
99
137
|
# Even if `variables: nil` is passed, use an empty hash for simpler logic
|
|
100
138
|
variables ||= {}
|
|
139
|
+
@multiplex = multiplex
|
|
101
140
|
@schema = schema
|
|
102
|
-
@context = schema.context_class.new(query: self,
|
|
103
|
-
|
|
141
|
+
@context = schema.context_class.new(query: self, values: context)
|
|
142
|
+
if visibility_profile
|
|
143
|
+
@context[:visibility_profile] ||= visibility_profile
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
if use_visibility_profile.nil?
|
|
147
|
+
use_visibility_profile = warden ? false : schema.use_visibility_profile?
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
if use_visibility_profile
|
|
151
|
+
@visibility_profile = @schema.visibility.profile_for(@context)
|
|
152
|
+
@warden = Schema::Warden::NullWarden.new(context: @context, schema: @schema)
|
|
153
|
+
else
|
|
154
|
+
@visibility_profile = nil
|
|
155
|
+
@warden = warden
|
|
156
|
+
end
|
|
157
|
+
|
|
104
158
|
@subscription_topic = subscription_topic
|
|
105
159
|
@root_value = root_value
|
|
106
160
|
@fragments = nil
|
|
@@ -110,15 +164,7 @@ module GraphQL
|
|
|
110
164
|
context_tracers = (context ? context.fetch(:tracers, []) : [])
|
|
111
165
|
@tracers = schema.tracers + context_tracers
|
|
112
166
|
|
|
113
|
-
|
|
114
|
-
if context && context[:backtrace] && !@tracers.include?(GraphQL::Backtrace::Tracer)
|
|
115
|
-
if schema.trace_class <= GraphQL::Tracing::CallLegacyTracers
|
|
116
|
-
context_tracers += [GraphQL::Backtrace::Tracer]
|
|
117
|
-
@tracers << GraphQL::Backtrace::Tracer
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
if context_tracers.any? && !(schema.trace_class <= GraphQL::Tracing::CallLegacyTracers)
|
|
167
|
+
if !context_tracers.empty? && !(schema.trace_class <= GraphQL::Tracing::CallLegacyTracers)
|
|
122
168
|
raise ArgumentError, "context[:tracers] are not supported without `trace_with(GraphQL::Tracing::CallLegacyTracers)` in the schema configuration, please add it."
|
|
123
169
|
end
|
|
124
170
|
|
|
@@ -161,13 +207,7 @@ module GraphQL
|
|
|
161
207
|
@result_values = nil
|
|
162
208
|
@executed = false
|
|
163
209
|
|
|
164
|
-
@logger =
|
|
165
|
-
Logger.new(IO::NULL)
|
|
166
|
-
elsif context && (l = context[:logger])
|
|
167
|
-
l
|
|
168
|
-
else
|
|
169
|
-
schema.default_logger
|
|
170
|
-
end
|
|
210
|
+
@logger = schema.logger_for(context)
|
|
171
211
|
end
|
|
172
212
|
|
|
173
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
|
|
@@ -175,9 +215,8 @@ module GraphQL
|
|
|
175
215
|
@query_string ||= (document ? document.to_query_string : nil)
|
|
176
216
|
end
|
|
177
217
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
end
|
|
218
|
+
# @return [Symbol, nil]
|
|
219
|
+
attr_reader :visibility_profile
|
|
181
220
|
|
|
182
221
|
attr_accessor :multiplex
|
|
183
222
|
|
|
@@ -194,9 +233,11 @@ module GraphQL
|
|
|
194
233
|
# @return [GraphQL::Execution::Lookahead]
|
|
195
234
|
def lookahead
|
|
196
235
|
@lookahead ||= begin
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
236
|
+
if selected_operation.nil?
|
|
237
|
+
GraphQL::Execution::Lookahead::NULL_LOOKAHEAD
|
|
238
|
+
else
|
|
239
|
+
GraphQL::Execution::Lookahead.new(query: self, root_type: root_type, ast_nodes: [selected_operation])
|
|
240
|
+
end
|
|
200
241
|
end
|
|
201
242
|
end
|
|
202
243
|
|
|
@@ -221,8 +262,20 @@ module GraphQL
|
|
|
221
262
|
with_prepared_ast { @operations }
|
|
222
263
|
end
|
|
223
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
|
+
|
|
224
277
|
# Get the result for this query, executing it once
|
|
225
|
-
# @return [
|
|
278
|
+
# @return [GraphQL::Query::Result] A Hash-like GraphQL response, with `"data"` and/or `"errors"` keys
|
|
226
279
|
def result
|
|
227
280
|
if !@executed
|
|
228
281
|
Execution::Interpreter.run_all(@schema, [self], context: @context)
|
|
@@ -263,19 +316,6 @@ module GraphQL
|
|
|
263
316
|
end
|
|
264
317
|
end
|
|
265
318
|
|
|
266
|
-
# Node-level cache for calculating arguments. Used during execution and query analysis.
|
|
267
|
-
# @param ast_node [GraphQL::Language::Nodes::AbstractNode]
|
|
268
|
-
# @param definition [GraphQL::Schema::Field]
|
|
269
|
-
# @param parent_object [GraphQL::Schema::Object]
|
|
270
|
-
# @return Hash{Symbol => Object}
|
|
271
|
-
def arguments_for(ast_node, definition, parent_object: nil)
|
|
272
|
-
arguments_cache.fetch(ast_node, definition, parent_object)
|
|
273
|
-
end
|
|
274
|
-
|
|
275
|
-
def arguments_cache
|
|
276
|
-
@arguments_cache ||= Execution::Interpreter::ArgumentsCache.new(self)
|
|
277
|
-
end
|
|
278
|
-
|
|
279
319
|
# A version of the given query string, with:
|
|
280
320
|
# - Variables inlined to the query
|
|
281
321
|
# - Strings replaced with `<REDACTED>`
|
|
@@ -304,7 +344,7 @@ module GraphQL
|
|
|
304
344
|
|
|
305
345
|
# @return [String] An opaque hash for identifying this query's given query string and selected operation
|
|
306
346
|
def operation_fingerprint
|
|
307
|
-
@operation_fingerprint ||= "#{selected_operation_name || "anonymous"}/#{Fingerprint.generate(query_string)}"
|
|
347
|
+
@operation_fingerprint ||= "#{selected_operation_name || "anonymous"}/#{Fingerprint.generate(query_string || "")}"
|
|
308
348
|
end
|
|
309
349
|
|
|
310
350
|
# @return [String] An opaque hash for identifying this query's given a variable values (not including defaults)
|
|
@@ -328,7 +368,38 @@ module GraphQL
|
|
|
328
368
|
with_prepared_ast { @warden }
|
|
329
369
|
end
|
|
330
370
|
|
|
331
|
-
|
|
371
|
+
def get_type(type_name)
|
|
372
|
+
types.type(type_name) # rubocop:disable Development/ContextIsPassedCop
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
def get_field(owner, field_name)
|
|
376
|
+
types.field(owner, field_name) # rubocop:disable Development/ContextIsPassedCop
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
def possible_types(type)
|
|
380
|
+
types.possible_types(type) # rubocop:disable Development/ContextIsPassedCop
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
def root_type_for_operation(op_type)
|
|
384
|
+
case op_type
|
|
385
|
+
when "query", nil
|
|
386
|
+
types.query_root # rubocop:disable Development/ContextIsPassedCop
|
|
387
|
+
when "mutation"
|
|
388
|
+
types.mutation_root # rubocop:disable Development/ContextIsPassedCop
|
|
389
|
+
when "subscription"
|
|
390
|
+
types.subscription_root # rubocop:disable Development/ContextIsPassedCop
|
|
391
|
+
else
|
|
392
|
+
raise ArgumentError, "unexpected root type name: #{op_type.inspect}; expected nil, 'query', 'mutation', or 'subscription'"
|
|
393
|
+
end
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
def root_type
|
|
397
|
+
root_type_for_operation(selected_operation.operation_type)
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
def types
|
|
401
|
+
@visibility_profile || warden.visibility_profile
|
|
402
|
+
end
|
|
332
403
|
|
|
333
404
|
# @param abstract_type [GraphQL::UnionType, GraphQL::InterfaceType]
|
|
334
405
|
# @param value [Object] Any runtime value
|
|
@@ -358,23 +429,6 @@ module GraphQL
|
|
|
358
429
|
with_prepared_ast { @subscription }
|
|
359
430
|
end
|
|
360
431
|
|
|
361
|
-
# @api private
|
|
362
|
-
def handle_or_reraise(err)
|
|
363
|
-
schema.handle_or_reraise(context, err)
|
|
364
|
-
end
|
|
365
|
-
|
|
366
|
-
def after_lazy(value, &block)
|
|
367
|
-
if !defined?(@runtime_instance)
|
|
368
|
-
@runtime_instance = context.namespace(:interpreter_runtime)[:runtime]
|
|
369
|
-
end
|
|
370
|
-
|
|
371
|
-
if @runtime_instance
|
|
372
|
-
@runtime_instance.minimal_after_lazy(value, &block)
|
|
373
|
-
else
|
|
374
|
-
@schema.after_lazy(value, &block)
|
|
375
|
-
end
|
|
376
|
-
end
|
|
377
|
-
|
|
378
432
|
attr_reader :logger
|
|
379
433
|
|
|
380
434
|
private
|
|
@@ -395,7 +449,7 @@ module GraphQL
|
|
|
395
449
|
parse_error = nil
|
|
396
450
|
@document ||= begin
|
|
397
451
|
if query_string
|
|
398
|
-
GraphQL.parse(query_string, trace: self.current_trace)
|
|
452
|
+
GraphQL.parse(query_string, trace: self.current_trace, max_tokens: @schema.max_query_string_tokens)
|
|
399
453
|
end
|
|
400
454
|
rescue GraphQL::ParseError => err
|
|
401
455
|
parse_error = err
|
|
@@ -427,7 +481,7 @@ module GraphQL
|
|
|
427
481
|
@mutation = false
|
|
428
482
|
@subscription = false
|
|
429
483
|
operation_name_error = nil
|
|
430
|
-
if
|
|
484
|
+
if !@operations.empty?
|
|
431
485
|
@selected_operation = find_operation(@operations, @operation_name)
|
|
432
486
|
if @selected_operation.nil?
|
|
433
487
|
operation_name_error = GraphQL::Query::OperationNameMissingError.new(@operation_name)
|
data/lib/graphql/railtie.rb
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module GraphQL
|
|
4
|
+
# Support {GraphQL::Parser::Cache} and {GraphQL.eager_load!}
|
|
5
|
+
#
|
|
6
|
+
# @example Enable the parser cache with default directory
|
|
7
|
+
#
|
|
8
|
+
# config.graphql.parser_cache = true
|
|
9
|
+
#
|
|
4
10
|
class Railtie < Rails::Railtie
|
|
5
11
|
config.graphql = ActiveSupport::OrderedOptions.new
|
|
6
12
|
config.graphql.parser_cache = false
|
|
13
|
+
config.eager_load_namespaces << GraphQL
|
|
7
14
|
|
|
8
15
|
initializer("graphql.cache") do |app|
|
|
9
16
|
if config.graphql.parser_cache
|
|
@@ -9,7 +9,7 @@ module GraphQL
|
|
|
9
9
|
|
|
10
10
|
# Return the source of `send_node`, but without the keyword argument represented by `pair_node`
|
|
11
11
|
def source_without_keyword_argument(send_node, pair_node)
|
|
12
|
-
# work back to the
|
|
12
|
+
# work back to the preceding comma
|
|
13
13
|
first_pos = pair_node.location.expression.begin_pos
|
|
14
14
|
end_pos = pair_node.location.expression.end_pos
|
|
15
15
|
node_source = send_node.source_range.source
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require_relative "./base_cop"
|
|
3
|
+
|
|
4
|
+
module GraphQL
|
|
5
|
+
module Rubocop
|
|
6
|
+
module GraphQL
|
|
7
|
+
# Identify (and auto-correct) any field whose type configuration isn't given
|
|
8
|
+
# in the configuration block.
|
|
9
|
+
#
|
|
10
|
+
# @example
|
|
11
|
+
# # bad, immediately causes Rails to load `app/graphql/types/thing.rb`
|
|
12
|
+
# field :thing, Types::Thing
|
|
13
|
+
#
|
|
14
|
+
# # good, defers loading until the file is needed
|
|
15
|
+
# field :thing do
|
|
16
|
+
# type(Types::Thing)
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
class FieldTypeInBlock < BaseCop
|
|
20
|
+
MSG = "type configuration can be moved to a block to defer loading the type's file"
|
|
21
|
+
|
|
22
|
+
BUILT_IN_SCALAR_NAMES = ["Float", "Int", "Integer", "String", "ID", "Boolean"]
|
|
23
|
+
def_node_matcher :field_config_with_inline_type, <<-Pattern
|
|
24
|
+
(
|
|
25
|
+
send {nil? _} :field sym ${const array} ...
|
|
26
|
+
)
|
|
27
|
+
Pattern
|
|
28
|
+
|
|
29
|
+
def_node_matcher :field_config_with_inline_type_and_block, <<-Pattern
|
|
30
|
+
(
|
|
31
|
+
block
|
|
32
|
+
(send {nil? _} :field sym ${const array} ...) ...
|
|
33
|
+
(args)
|
|
34
|
+
_
|
|
35
|
+
|
|
36
|
+
)
|
|
37
|
+
Pattern
|
|
38
|
+
|
|
39
|
+
def on_block(node)
|
|
40
|
+
ignore_node(node)
|
|
41
|
+
field_config_with_inline_type_and_block(node) do |type_const|
|
|
42
|
+
type_const_str = get_type_argument_str(node, type_const)
|
|
43
|
+
if ignore_inline_type_str?(type_const_str)
|
|
44
|
+
# Do nothing ...
|
|
45
|
+
else
|
|
46
|
+
add_offense(type_const) do |corrector|
|
|
47
|
+
cleaned_node_source = delete_type_argument(node, type_const)
|
|
48
|
+
field_indent = determine_field_indent(node)
|
|
49
|
+
cleaned_node_source.sub!(/(\{|do)/, "\\1\n#{field_indent} type #{type_const_str}")
|
|
50
|
+
corrector.replace(node, cleaned_node_source)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def on_send(node)
|
|
57
|
+
return if part_of_ignored_node?(node)
|
|
58
|
+
field_config_with_inline_type(node) do |type_const|
|
|
59
|
+
type_const_str = get_type_argument_str(node, type_const)
|
|
60
|
+
if ignore_inline_type_str?(type_const_str)
|
|
61
|
+
# Do nothing -- not loading from another file
|
|
62
|
+
else
|
|
63
|
+
add_offense(type_const) do |corrector|
|
|
64
|
+
cleaned_node_source = delete_type_argument(node, type_const)
|
|
65
|
+
field_indent = determine_field_indent(node)
|
|
66
|
+
cleaned_node_source += " do\n#{field_indent} type #{type_const_str}\n#{field_indent}end"
|
|
67
|
+
corrector.replace(node, cleaned_node_source)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
|
|
76
|
+
def ignore_inline_type_str?(type_str)
|
|
77
|
+
if BUILT_IN_SCALAR_NAMES.include?(type_str)
|
|
78
|
+
true
|
|
79
|
+
elsif (inner_type_str = type_str.sub(/\[([A-Za-z]+)(, null: (true|false))?\]/, '\1')) && BUILT_IN_SCALAR_NAMES.include?(inner_type_str)
|
|
80
|
+
true
|
|
81
|
+
else
|
|
82
|
+
false
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def get_type_argument_str(send_node, type_const)
|
|
87
|
+
first_pos = type_const.location.expression.begin_pos
|
|
88
|
+
end_pos = type_const.location.expression.end_pos
|
|
89
|
+
node_source = send_node.source_range.source
|
|
90
|
+
node_first_pos = send_node.location.expression.begin_pos
|
|
91
|
+
|
|
92
|
+
relative_first_pos = first_pos - node_first_pos
|
|
93
|
+
end_removal_pos = end_pos - node_first_pos
|
|
94
|
+
|
|
95
|
+
node_source[relative_first_pos...end_removal_pos]
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def delete_type_argument(send_node, type_const)
|
|
99
|
+
first_pos = type_const.location.expression.begin_pos
|
|
100
|
+
end_pos = type_const.location.expression.end_pos
|
|
101
|
+
node_source = send_node.source_range.source
|
|
102
|
+
node_first_pos = send_node.location.expression.begin_pos
|
|
103
|
+
|
|
104
|
+
relative_first_pos = first_pos - node_first_pos
|
|
105
|
+
end_removal_pos = end_pos - node_first_pos
|
|
106
|
+
|
|
107
|
+
begin_removal_pos = relative_first_pos
|
|
108
|
+
while node_source[begin_removal_pos] != ","
|
|
109
|
+
begin_removal_pos -= 1
|
|
110
|
+
if begin_removal_pos < 1
|
|
111
|
+
raise "Invariant: somehow backtracked to beginning of node looking for a comma (node source: #{node_source.inspect})"
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
node_source[0...begin_removal_pos] + node_source[end_removal_pos..-1]
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def determine_field_indent(send_node)
|
|
119
|
+
type_defn_node = send_node
|
|
120
|
+
|
|
121
|
+
while (type_defn_node && !(type_defn_node.class_definition? || type_defn_node.module_definition?))
|
|
122
|
+
type_defn_node = type_defn_node.parent
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
if type_defn_node.nil?
|
|
126
|
+
raise "Invariant: Something went wrong in GraphQL-Ruby, couldn't find surrounding class definition for field (#{send_node}).\n\nPlease report this error on GitHub."
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
type_defn_source = type_defn_node.source
|
|
130
|
+
indent_test_idx = send_node.location.expression.begin_pos - type_defn_node.source_range.begin_pos - 1
|
|
131
|
+
field_indent = "".dup
|
|
132
|
+
while type_defn_source[indent_test_idx] == " "
|
|
133
|
+
field_indent << " "
|
|
134
|
+
indent_test_idx -= 1
|
|
135
|
+
if indent_test_idx == 0
|
|
136
|
+
raise "Invariant: somehow backtracted to beginning of class when looking for field indent (source: #{node_source.inspect})"
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
field_indent
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require_relative "./base_cop"
|
|
3
|
+
|
|
4
|
+
module GraphQL
|
|
5
|
+
module Rubocop
|
|
6
|
+
module GraphQL
|
|
7
|
+
# Identify (and auto-correct) any root types in your schema file.
|
|
8
|
+
#
|
|
9
|
+
# @example
|
|
10
|
+
# # bad, immediately causes Rails to load `app/graphql/types/query.rb`
|
|
11
|
+
# query Types::Query
|
|
12
|
+
#
|
|
13
|
+
# # good, defers loading until the file is needed
|
|
14
|
+
# query { Types::Query }
|
|
15
|
+
#
|
|
16
|
+
class RootTypesInBlock < BaseCop
|
|
17
|
+
MSG = "type configuration can be moved to a block to defer loading the type's file"
|
|
18
|
+
|
|
19
|
+
def_node_matcher :root_type_config_without_block, <<-Pattern
|
|
20
|
+
(
|
|
21
|
+
send nil? {:query :mutation :subscription} const
|
|
22
|
+
)
|
|
23
|
+
Pattern
|
|
24
|
+
|
|
25
|
+
def on_send(node)
|
|
26
|
+
root_type_config_without_block(node) do
|
|
27
|
+
add_offense(node) do |corrector|
|
|
28
|
+
new_node_source = node.source_range.source
|
|
29
|
+
new_node_source.sub!(/(query|mutation|subscription)/, '\1 {')
|
|
30
|
+
new_node_source << " }"
|
|
31
|
+
corrector.replace(node, new_node_source)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
data/lib/graphql/rubocop.rb
CHANGED
|
@@ -12,7 +12,7 @@ module GraphQL
|
|
|
12
12
|
@possible_types = {}
|
|
13
13
|
@types = {}
|
|
14
14
|
@union_memberships = {}
|
|
15
|
-
@references = Hash.new { |h, k| h[k] =
|
|
15
|
+
@references = Hash.new { |h, k| h[k] = Set.new }
|
|
16
16
|
@arguments_with_default_values = []
|
|
17
17
|
add_type_and_traverse(new_types)
|
|
18
18
|
end
|
|
@@ -20,7 +20,7 @@ module GraphQL
|
|
|
20
20
|
private
|
|
21
21
|
|
|
22
22
|
def references_to(thing, from:)
|
|
23
|
-
@references[thing]
|
|
23
|
+
@references[thing].add(from)
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def get_type(name)
|
|
@@ -40,7 +40,7 @@ module GraphQL
|
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
def add_directives_from(owner)
|
|
43
|
-
if (dir_instances = owner.directives).
|
|
43
|
+
if !(dir_instances = owner.directives).empty?
|
|
44
44
|
dirs = dir_instances.map(&:class)
|
|
45
45
|
@directives.merge(dirs)
|
|
46
46
|
add_type_and_traverse(dirs)
|
|
@@ -95,7 +95,7 @@ module GraphQL
|
|
|
95
95
|
# It's a union with possible_types
|
|
96
96
|
# Replace the item by class name
|
|
97
97
|
owner.assign_type_membership_object_type(type)
|
|
98
|
-
@possible_types[owner
|
|
98
|
+
@possible_types[owner] = owner.possible_types
|
|
99
99
|
elsif type.kind.interface? && (owner.kind.object? || owner.kind.interface?)
|
|
100
100
|
new_interfaces = []
|
|
101
101
|
owner.interfaces.each do |int_t|
|
|
@@ -110,7 +110,7 @@ module GraphQL
|
|
|
110
110
|
end
|
|
111
111
|
owner.implements(*new_interfaces)
|
|
112
112
|
new_interfaces.each do |int|
|
|
113
|
-
pt = @possible_types[int
|
|
113
|
+
pt = @possible_types[int] ||= []
|
|
114
114
|
if !pt.include?(owner) && owner.is_a?(Class)
|
|
115
115
|
pt << owner
|
|
116
116
|
end
|
|
@@ -126,6 +126,7 @@ module GraphQL
|
|
|
126
126
|
@types[type.graphql_name] = type
|
|
127
127
|
when GraphQL::Schema::Field, GraphQL::Schema::Argument
|
|
128
128
|
orig_type = owner.type
|
|
129
|
+
unwrapped_t = type
|
|
129
130
|
# Apply list/non-null wrapper as needed
|
|
130
131
|
if orig_type.respond_to?(:of_type)
|
|
131
132
|
transforms = []
|
|
@@ -142,6 +143,7 @@ module GraphQL
|
|
|
142
143
|
transforms.reverse_each { |t| type = type.public_send(t) }
|
|
143
144
|
end
|
|
144
145
|
owner.type = type
|
|
146
|
+
references_to(unwrapped_t, from: owner)
|
|
145
147
|
else
|
|
146
148
|
raise "Unexpected update: #{owner.inspect} #{type.inspect}"
|
|
147
149
|
end
|
|
@@ -164,7 +166,9 @@ module GraphQL
|
|
|
164
166
|
@directives << type
|
|
165
167
|
type.all_argument_definitions.each do |arg|
|
|
166
168
|
arg_type = arg.type.unwrap
|
|
167
|
-
|
|
169
|
+
if !arg_type.is_a?(GraphQL::Schema::LateBoundType)
|
|
170
|
+
references_to(arg_type, from: arg)
|
|
171
|
+
end
|
|
168
172
|
path.push(arg.graphql_name)
|
|
169
173
|
add_type(arg_type, owner: arg, late_types: late_types, path: path)
|
|
170
174
|
path.pop
|
|
@@ -185,16 +189,21 @@ module GraphQL
|
|
|
185
189
|
add_directives_from(type)
|
|
186
190
|
if type.kind.fields?
|
|
187
191
|
type.all_field_definitions.each do |field|
|
|
192
|
+
field.ensure_loaded
|
|
188
193
|
name = field.graphql_name
|
|
189
194
|
field_type = field.type.unwrap
|
|
190
|
-
|
|
195
|
+
if !field_type.is_a?(GraphQL::Schema::LateBoundType)
|
|
196
|
+
references_to(field_type, from: field)
|
|
197
|
+
end
|
|
191
198
|
path.push(name)
|
|
192
199
|
add_type(field_type, owner: field, late_types: late_types, path: path)
|
|
193
200
|
add_directives_from(field)
|
|
194
201
|
field.all_argument_definitions.each do |arg|
|
|
195
202
|
add_directives_from(arg)
|
|
196
203
|
arg_type = arg.type.unwrap
|
|
197
|
-
|
|
204
|
+
if !arg_type.is_a?(GraphQL::Schema::LateBoundType)
|
|
205
|
+
references_to(arg_type, from: arg)
|
|
206
|
+
end
|
|
198
207
|
path.push(arg.graphql_name)
|
|
199
208
|
add_type(arg_type, owner: arg, late_types: late_types, path: path)
|
|
200
209
|
path.pop
|
|
@@ -209,7 +218,9 @@ module GraphQL
|
|
|
209
218
|
type.all_argument_definitions.each do |arg|
|
|
210
219
|
add_directives_from(arg)
|
|
211
220
|
arg_type = arg.type.unwrap
|
|
212
|
-
|
|
221
|
+
if !arg_type.is_a?(GraphQL::Schema::LateBoundType)
|
|
222
|
+
references_to(arg_type, from: arg)
|
|
223
|
+
end
|
|
213
224
|
path.push(arg.graphql_name)
|
|
214
225
|
add_type(arg_type, owner: arg, late_types: late_types, path: path)
|
|
215
226
|
path.pop
|
|
@@ -219,7 +230,7 @@ module GraphQL
|
|
|
219
230
|
end
|
|
220
231
|
end
|
|
221
232
|
if type.kind.union?
|
|
222
|
-
@possible_types[type
|
|
233
|
+
@possible_types[type] = type.all_possible_types
|
|
223
234
|
path.push("possible_types")
|
|
224
235
|
type.all_possible_types.each do |t|
|
|
225
236
|
add_type(t, owner: type, late_types: late_types, path: path)
|
|
@@ -234,7 +245,7 @@ module GraphQL
|
|
|
234
245
|
path.pop
|
|
235
246
|
end
|
|
236
247
|
if type.kind.object?
|
|
237
|
-
possible_types_for_this_name = @possible_types[type
|
|
248
|
+
possible_types_for_this_name = @possible_types[type] ||= []
|
|
238
249
|
possible_types_for_this_name << type
|
|
239
250
|
end
|
|
240
251
|
|
|
@@ -246,8 +257,10 @@ module GraphQL
|
|
|
246
257
|
interface_type = interface_type_membership.abstract_type
|
|
247
258
|
# We can get these now; we'll have to get late-bound types later
|
|
248
259
|
if interface_type.is_a?(Module) && type.is_a?(Class)
|
|
249
|
-
implementers = @possible_types[interface_type
|
|
250
|
-
implementers
|
|
260
|
+
implementers = @possible_types[interface_type] ||= []
|
|
261
|
+
if !implementers.include?(type)
|
|
262
|
+
implementers << type
|
|
263
|
+
end
|
|
251
264
|
end
|
|
252
265
|
when String, Schema::LateBoundType
|
|
253
266
|
interface_type = interface_type_membership
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
module GraphQL
|
|
3
3
|
class Schema
|
|
4
|
-
|
|
4
|
+
module AlwaysVisible
|
|
5
5
|
def self.use(schema, **opts)
|
|
6
|
-
schema.
|
|
6
|
+
schema.use(GraphQL::Schema::Visibility, profiles: { nil => {} })
|
|
7
|
+
schema.extend(self)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def visible?(_member, _context)
|
|
11
|
+
true
|
|
7
12
|
end
|
|
8
13
|
end
|
|
9
14
|
end
|