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
|
@@ -26,7 +26,7 @@ module GraphQL
|
|
|
26
26
|
context.directive_definition || context.field_definition
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
-
parent_type = context.
|
|
29
|
+
parent_type = context.types.argument(defn, parent_name(parent, defn))
|
|
30
30
|
parent_type ? parent_type.type.unwrap : nil
|
|
31
31
|
end
|
|
32
32
|
|
|
@@ -34,7 +34,7 @@ module GraphQL
|
|
|
34
34
|
parent_type = get_parent_type(context, parent)
|
|
35
35
|
return unless parent_type && parent_type.kind.input_object?
|
|
36
36
|
|
|
37
|
-
required_fields = context.
|
|
37
|
+
required_fields = context.types.arguments(parent_type)
|
|
38
38
|
.select{ |arg| arg.type.kind.non_null? && !arg.default_value? }
|
|
39
39
|
.map!(&:graphql_name)
|
|
40
40
|
|
|
@@ -43,7 +43,7 @@ module GraphQL
|
|
|
43
43
|
|
|
44
44
|
missing_fields.each do |missing_field|
|
|
45
45
|
path = [*context.path, missing_field]
|
|
46
|
-
missing_field_type = context.
|
|
46
|
+
missing_field_type = context.types.argument(parent_type, missing_field).type
|
|
47
47
|
add_error(RequiredInputObjectAttributesArePresentError.new(
|
|
48
48
|
"Argument '#{missing_field}' on InputObject '#{parent_type.to_type_signature}' is required. Expected type #{missing_field_type.to_type_signature}",
|
|
49
49
|
argument_name: missing_field,
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module GraphQL
|
|
3
|
+
module StaticValidation
|
|
4
|
+
module SubscriptionRootExistsAndSingleSubscriptionSelection
|
|
5
|
+
def on_operation_definition(node, parent)
|
|
6
|
+
if node.operation_type == "subscription"
|
|
7
|
+
if context.types.subscription_root.nil?
|
|
8
|
+
add_error(GraphQL::StaticValidation::SubscriptionRootExistsError.new(
|
|
9
|
+
'Schema is not configured for subscriptions',
|
|
10
|
+
nodes: node
|
|
11
|
+
))
|
|
12
|
+
elsif node.selections.size != 1
|
|
13
|
+
add_error(GraphQL::StaticValidation::NotSingleSubscriptionError.new(
|
|
14
|
+
'A subscription operation may only have one selection',
|
|
15
|
+
nodes: node,
|
|
16
|
+
))
|
|
17
|
+
else
|
|
18
|
+
super
|
|
19
|
+
end
|
|
20
|
+
else
|
|
21
|
+
super
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -19,13 +19,17 @@ module GraphQL
|
|
|
19
19
|
:on_field,
|
|
20
20
|
]
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if node.directives.
|
|
22
|
+
VALIDATE_DIRECTIVE_LOCATION_ON_NODE = <<~RUBY
|
|
23
|
+
def %{method_name}(node, parent)
|
|
24
|
+
if !node.directives.empty?
|
|
25
25
|
validate_directive_location(node)
|
|
26
26
|
end
|
|
27
27
|
super(node, parent)
|
|
28
28
|
end
|
|
29
|
+
RUBY
|
|
30
|
+
DIRECTIVE_NODE_HOOKS.each do |method_name|
|
|
31
|
+
# Can't use `define_method {...}` here because the proc can't be isolated for use in non-main Ractors
|
|
32
|
+
module_eval(VALIDATE_DIRECTIVE_LOCATION_ON_NODE % { method_name: method_name }) # rubocop:disable Development/NoEvalCop
|
|
29
33
|
end
|
|
30
34
|
|
|
31
35
|
private
|
|
@@ -5,36 +5,27 @@ module GraphQL
|
|
|
5
5
|
def on_variable_definition(node, parent)
|
|
6
6
|
if !node.default_value.nil?
|
|
7
7
|
value = node.default_value
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
nodes: node,
|
|
12
|
-
name: node.name,
|
|
13
|
-
error_type: VariableDefaultValuesAreCorrectlyTypedError::VIOLATIONS[:INVALID_ON_NON_NULL]
|
|
14
|
-
))
|
|
8
|
+
type = context.schema.type_from_ast(node.type, context: context)
|
|
9
|
+
if type.nil?
|
|
10
|
+
# This is handled by another validator
|
|
15
11
|
else
|
|
16
|
-
|
|
17
|
-
if type.nil?
|
|
18
|
-
# This is handled by another validator
|
|
19
|
-
else
|
|
20
|
-
validation_result = context.validate_literal(value, type)
|
|
12
|
+
validation_result = context.validate_literal(value, type)
|
|
21
13
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
error_message ||= "Default value for $#{node.name} doesn't match type #{type.to_type_signature}"
|
|
30
|
-
add_error(GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTypedError.new(
|
|
31
|
-
error_message,
|
|
32
|
-
nodes: node,
|
|
33
|
-
name: node.name,
|
|
34
|
-
type: type.to_type_signature,
|
|
35
|
-
error_type: VariableDefaultValuesAreCorrectlyTypedError::VIOLATIONS[:INVALID_TYPE],
|
|
36
|
-
))
|
|
14
|
+
if !validation_result.valid?
|
|
15
|
+
problems = validation_result.problems
|
|
16
|
+
first_problem = problems && problems.first
|
|
17
|
+
if first_problem
|
|
18
|
+
error_message = first_problem["explanation"]
|
|
37
19
|
end
|
|
20
|
+
|
|
21
|
+
error_message ||= "Default value for $#{node.name} doesn't match type #{type.to_type_signature}"
|
|
22
|
+
add_error(GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTypedError.new(
|
|
23
|
+
error_message,
|
|
24
|
+
nodes: node,
|
|
25
|
+
name: node.name,
|
|
26
|
+
type: type.to_type_signature,
|
|
27
|
+
error_type: VariableDefaultValuesAreCorrectlyTypedError::VIOLATIONS[:INVALID_TYPE],
|
|
28
|
+
))
|
|
38
29
|
end
|
|
39
30
|
end
|
|
40
31
|
end
|
|
@@ -4,7 +4,7 @@ module GraphQL
|
|
|
4
4
|
module VariableNamesAreUnique
|
|
5
5
|
def on_operation_definition(node, parent)
|
|
6
6
|
var_defns = node.variables
|
|
7
|
-
if var_defns.
|
|
7
|
+
if !var_defns.empty?
|
|
8
8
|
vars_by_name = Hash.new { |h, k| h[k] = [] }
|
|
9
9
|
var_defns.each { |v| vars_by_name[v.name] << v }
|
|
10
10
|
vars_by_name.each do |name, defns|
|
|
@@ -21,7 +21,7 @@ module GraphQL
|
|
|
21
21
|
end
|
|
22
22
|
node_values = node_values.select { |value| value.is_a? GraphQL::Language::Nodes::VariableIdentifier }
|
|
23
23
|
|
|
24
|
-
if node_values.
|
|
24
|
+
if !node_values.empty?
|
|
25
25
|
argument_owner = case parent
|
|
26
26
|
when GraphQL::Language::Nodes::Field
|
|
27
27
|
context.field_definition
|
|
@@ -65,7 +65,7 @@ module GraphQL
|
|
|
65
65
|
end
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
-
arg_defn =
|
|
68
|
+
arg_defn = @types.argument(argument_owner, arg_node.name)
|
|
69
69
|
arg_defn_type = arg_defn.type
|
|
70
70
|
|
|
71
71
|
# If the argument is non-null, but it was given a default value,
|
|
@@ -4,11 +4,20 @@ module GraphQL
|
|
|
4
4
|
module VariablesAreInputTypes
|
|
5
5
|
def on_variable_definition(node, parent)
|
|
6
6
|
type_name = get_type_name(node.type)
|
|
7
|
-
type = context.
|
|
7
|
+
type = context.query.types.type(type_name)
|
|
8
8
|
|
|
9
9
|
if type.nil?
|
|
10
|
+
@all_possible_input_type_names ||= begin
|
|
11
|
+
names = []
|
|
12
|
+
context.types.all_types.each { |(t)|
|
|
13
|
+
if t.kind.input?
|
|
14
|
+
names << t.graphql_name
|
|
15
|
+
end
|
|
16
|
+
}
|
|
17
|
+
names
|
|
18
|
+
end
|
|
10
19
|
add_error(GraphQL::StaticValidation::VariablesAreInputTypesError.new(
|
|
11
|
-
"#{type_name} isn't a defined input type (on $#{node.name})",
|
|
20
|
+
"#{type_name} isn't a defined input type (on $#{node.name})#{context.did_you_mean_suggestion(type_name, @all_possible_input_type_names)}",
|
|
12
21
|
nodes: node,
|
|
13
22
|
name: node.name,
|
|
14
23
|
type: type_name
|
|
@@ -13,14 +13,14 @@ module GraphQL
|
|
|
13
13
|
|
|
14
14
|
attr_reader :query, :errors, :visitor,
|
|
15
15
|
:on_dependency_resolve_handlers,
|
|
16
|
-
:max_errors, :
|
|
16
|
+
:max_errors, :types, :schema
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
def_delegators :@query, :document, :fragments, :operations
|
|
20
20
|
|
|
21
21
|
def initialize(query, visitor_class, max_errors)
|
|
22
22
|
@query = query
|
|
23
|
-
@
|
|
23
|
+
@types = query.types # TODO update migrated callers to use this accessor
|
|
24
24
|
@schema = query.schema
|
|
25
25
|
@literal_validator = LiteralValidator.new(context: query.context)
|
|
26
26
|
@errors = []
|
|
@@ -29,6 +29,7 @@ module GraphQL
|
|
|
29
29
|
@visitor = visitor_class.new(document, self)
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
+
# TODO stop using def_delegators because of Array allocations
|
|
32
33
|
def_delegators :@visitor,
|
|
33
34
|
:path, :type_definition, :field_definition, :argument_definition,
|
|
34
35
|
:parent_type_definition, :directive_definition, :object_types, :dependencies
|
|
@@ -48,6 +49,21 @@ module GraphQL
|
|
|
48
49
|
def schema_directives
|
|
49
50
|
@schema_directives ||= schema.directives
|
|
50
51
|
end
|
|
52
|
+
|
|
53
|
+
def did_you_mean_suggestion(name, options)
|
|
54
|
+
if did_you_mean = schema.did_you_mean
|
|
55
|
+
suggestions = did_you_mean::SpellChecker.new(dictionary: options).correct(name)
|
|
56
|
+
case suggestions.size
|
|
57
|
+
when 0
|
|
58
|
+
""
|
|
59
|
+
when 1
|
|
60
|
+
" (Did you mean `#{suggestions.first}`?)"
|
|
61
|
+
else
|
|
62
|
+
last_sugg = suggestions.pop
|
|
63
|
+
" (Did you mean #{suggestions.map {|s| "`#{s}`"}.join(", ")} or `#{last_sugg}`?)"
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
51
67
|
end
|
|
52
68
|
end
|
|
53
69
|
end
|
|
@@ -27,6 +27,8 @@ module GraphQL
|
|
|
27
27
|
# @param max_errors [Integer] Maximum number of errors before aborting validation. Any positive number will limit the number of errors. Defaults to nil for no limit.
|
|
28
28
|
# @return [Array<Hash>]
|
|
29
29
|
def validate(query, validate: true, timeout: nil, max_errors: nil)
|
|
30
|
+
errors = nil
|
|
31
|
+
query.current_trace.begin_validate(query, validate)
|
|
30
32
|
query.current_trace.validate(validate: validate, query: query) do
|
|
31
33
|
begin_t = Time.now
|
|
32
34
|
errors = if validate == false
|
|
@@ -58,10 +60,13 @@ module GraphQL
|
|
|
58
60
|
}
|
|
59
61
|
end
|
|
60
62
|
rescue GraphQL::ExecutionError => e
|
|
63
|
+
errors = [e]
|
|
61
64
|
{
|
|
62
65
|
remaining_timeout: nil,
|
|
63
|
-
errors:
|
|
66
|
+
errors: errors,
|
|
64
67
|
}
|
|
68
|
+
ensure
|
|
69
|
+
query.current_trace.end_validate(query, validate, errors)
|
|
65
70
|
end
|
|
66
71
|
|
|
67
72
|
# Invoked when static validation times out.
|
|
@@ -81,6 +81,7 @@ module GraphQL
|
|
|
81
81
|
# end
|
|
82
82
|
# end
|
|
83
83
|
#
|
|
84
|
+
# @see GraphQL::Testing::MockActionCable for test helpers
|
|
84
85
|
class ActionCableSubscriptions < GraphQL::Subscriptions
|
|
85
86
|
SUBSCRIPTION_PREFIX = "graphql-subscription:"
|
|
86
87
|
EVENT_PREFIX = "graphql-event:"
|
|
@@ -107,7 +108,7 @@ module GraphQL
|
|
|
107
108
|
when 2
|
|
108
109
|
true
|
|
109
110
|
else
|
|
110
|
-
raise ArgumentError, "#{@serializer} must
|
|
111
|
+
raise ArgumentError, "#{@serializer} must respond to `.load` accepting one or two arguments"
|
|
111
112
|
end
|
|
112
113
|
@transmit_ns = namespace
|
|
113
114
|
super
|
|
@@ -166,11 +167,12 @@ module GraphQL
|
|
|
166
167
|
#
|
|
167
168
|
def setup_stream(channel, initial_event)
|
|
168
169
|
topic = initial_event.topic
|
|
169
|
-
|
|
170
|
+
event_stream = stream_event_name(initial_event)
|
|
171
|
+
channel.stream_from(event_stream, coder: @action_cable_coder) do |message|
|
|
170
172
|
events_by_fingerprint = @events[topic]
|
|
171
173
|
object = nil
|
|
172
174
|
events_by_fingerprint.each do |_fingerprint, events|
|
|
173
|
-
if events.
|
|
175
|
+
if !events.empty? && events.first == initial_event
|
|
174
176
|
# The fingerprint has told us that this response should be shared by all subscribers,
|
|
175
177
|
# so just run it once, then deliver the result to every subscriber
|
|
176
178
|
first_event = events.first
|
|
@@ -9,7 +9,7 @@ module GraphQL
|
|
|
9
9
|
# Assign the result to `context.namespace(:subscriptions)[:subscription_broadcastable]`
|
|
10
10
|
# @api private
|
|
11
11
|
# @see Subscriptions#broadcastable? for a public API
|
|
12
|
-
class BroadcastAnalyzer < GraphQL::Analysis::
|
|
12
|
+
class BroadcastAnalyzer < GraphQL::Analysis::Analyzer
|
|
13
13
|
def initialize(subject)
|
|
14
14
|
super
|
|
15
15
|
@default_broadcastable = subject.schema.subscriptions.default_broadcastable
|
|
@@ -28,9 +28,8 @@ module GraphQL
|
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
current_field = visitor.field_definition
|
|
31
|
-
apply_broadcastable(current_field)
|
|
32
|
-
|
|
33
31
|
current_type = visitor.parent_type_definition
|
|
32
|
+
apply_broadcastable(current_type, current_field)
|
|
34
33
|
if current_type.kind.interface?
|
|
35
34
|
pt = @query.possible_types(current_type)
|
|
36
35
|
pt.each do |object_type|
|
|
@@ -38,7 +37,7 @@ module GraphQL
|
|
|
38
37
|
# Inherited fields would be exactly the same object;
|
|
39
38
|
# only check fields that are overrides of the inherited one
|
|
40
39
|
if ot_field && ot_field != current_field
|
|
41
|
-
apply_broadcastable(ot_field)
|
|
40
|
+
apply_broadcastable(object_type, ot_field)
|
|
42
41
|
end
|
|
43
42
|
end
|
|
44
43
|
end
|
|
@@ -55,10 +54,16 @@ module GraphQL
|
|
|
55
54
|
private
|
|
56
55
|
|
|
57
56
|
# Modify `@subscription_broadcastable` based on `field_defn`'s configuration (and/or the default value)
|
|
58
|
-
def apply_broadcastable(field_defn)
|
|
57
|
+
def apply_broadcastable(owner_type, field_defn)
|
|
59
58
|
current_field_broadcastable = field_defn.introspection? || field_defn.broadcastable?
|
|
59
|
+
|
|
60
|
+
if current_field_broadcastable.nil? && owner_type.respond_to?(:default_broadcastable?)
|
|
61
|
+
current_field_broadcastable = owner_type.default_broadcastable?
|
|
62
|
+
end
|
|
63
|
+
|
|
60
64
|
case current_field_broadcastable
|
|
61
65
|
when nil
|
|
66
|
+
query.logger.debug { "`broadcastable: nil` for field: #{field_defn.path}" }
|
|
62
67
|
# If the value wasn't set, mix in the default value:
|
|
63
68
|
# - If the default is false and the current value is true, make it false
|
|
64
69
|
# - If the default is true and the current value is true, it stays true
|
|
@@ -66,6 +71,7 @@ module GraphQL
|
|
|
66
71
|
# - If the default is true and the current value is false, keep it false
|
|
67
72
|
@subscription_broadcastable = @subscription_broadcastable && @default_broadcastable
|
|
68
73
|
when false
|
|
74
|
+
query.logger.debug { "`broadcastable: false` for field: #{field_defn.path}" }
|
|
69
75
|
# One non-broadcastable field is enough to make the whole subscription non-broadcastable
|
|
70
76
|
@subscription_broadcastable = false
|
|
71
77
|
when true
|
|
@@ -20,12 +20,22 @@ module GraphQL
|
|
|
20
20
|
def after_resolve(value:, context:, object:, arguments:, **rest)
|
|
21
21
|
if value.is_a?(GraphQL::ExecutionError)
|
|
22
22
|
value
|
|
23
|
+
elsif @field.resolver&.method_defined?(:subscription_written?) &&
|
|
24
|
+
(subscription_namespace = context.namespace(:subscriptions)) &&
|
|
25
|
+
(subscriptions_by_path = subscription_namespace[:subscriptions])
|
|
26
|
+
(subscription_instance = subscriptions_by_path[context.current_path])
|
|
27
|
+
# If it was already written, don't append this event to be written later
|
|
28
|
+
if !subscription_instance.subscription_written?
|
|
29
|
+
events = context.namespace(:subscriptions)[:events]
|
|
30
|
+
events << subscription_instance.event
|
|
31
|
+
end
|
|
32
|
+
value
|
|
23
33
|
elsif (events = context.namespace(:subscriptions)[:events])
|
|
24
34
|
# This is the first execution, so gather an Event
|
|
25
35
|
# for the backend to register:
|
|
26
36
|
event = Subscriptions::Event.new(
|
|
27
37
|
name: field.name,
|
|
28
|
-
arguments:
|
|
38
|
+
arguments: arguments,
|
|
29
39
|
context: context,
|
|
30
40
|
field: field,
|
|
31
41
|
)
|
|
@@ -33,7 +43,7 @@ module GraphQL
|
|
|
33
43
|
value
|
|
34
44
|
elsif context.query.subscription_topic == Subscriptions::Event.serialize(
|
|
35
45
|
field.name,
|
|
36
|
-
|
|
46
|
+
arguments,
|
|
37
47
|
field,
|
|
38
48
|
scope: (field.subscription_scope ? context[field.subscription_scope] : nil),
|
|
39
49
|
)
|
|
@@ -45,14 +55,6 @@ module GraphQL
|
|
|
45
55
|
context.skip
|
|
46
56
|
end
|
|
47
57
|
end
|
|
48
|
-
|
|
49
|
-
private
|
|
50
|
-
|
|
51
|
-
def arguments_without_field_extras(arguments:)
|
|
52
|
-
arguments.dup.tap do |event_args|
|
|
53
|
-
field.extras.each { |k| event_args.delete(k) }
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
58
|
end
|
|
57
59
|
end
|
|
58
60
|
end
|
|
@@ -20,7 +20,7 @@ module GraphQL
|
|
|
20
20
|
|
|
21
21
|
def initialize(name:, arguments:, field: nil, context: nil, scope: nil)
|
|
22
22
|
@name = name
|
|
23
|
-
@arguments = arguments
|
|
23
|
+
@arguments = self.class.arguments_without_field_extras(arguments: arguments, field: field)
|
|
24
24
|
@context = context
|
|
25
25
|
field ||= context.field
|
|
26
26
|
scope_key = field.subscription_scope
|
|
@@ -39,6 +39,7 @@ module GraphQL
|
|
|
39
39
|
# @return [String] an identifier for this unit of subscription
|
|
40
40
|
def self.serialize(_name, arguments, field, scope:, context: GraphQL::Query::NullContext.instance)
|
|
41
41
|
subscription = field.resolver || GraphQL::Schema::Subscription
|
|
42
|
+
arguments = arguments_without_field_extras(field: field, arguments: arguments)
|
|
42
43
|
normalized_args = stringify_args(field, arguments.to_h, context)
|
|
43
44
|
subscription.topic_for(arguments: normalized_args, field: field, scope: scope)
|
|
44
45
|
end
|
|
@@ -60,6 +61,16 @@ module GraphQL
|
|
|
60
61
|
end
|
|
61
62
|
|
|
62
63
|
class << self
|
|
64
|
+
def arguments_without_field_extras(arguments:, field:)
|
|
65
|
+
if !field.extras.empty?
|
|
66
|
+
arguments = arguments.dup
|
|
67
|
+
field.extras.each do |extra_key|
|
|
68
|
+
arguments.delete(extra_key)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
arguments
|
|
72
|
+
end
|
|
73
|
+
|
|
63
74
|
private
|
|
64
75
|
|
|
65
76
|
# This method does not support cyclic references in the Hash,
|
|
@@ -137,7 +148,7 @@ module GraphQL
|
|
|
137
148
|
end
|
|
138
149
|
|
|
139
150
|
def get_arg_definition(arg_owner, arg_name, context)
|
|
140
|
-
|
|
151
|
+
context.types.argument(arg_owner, arg_name) || context.types.arguments(arg_owner).find { |v| v.keyword.to_s == arg_name }
|
|
141
152
|
end
|
|
142
153
|
end
|
|
143
154
|
end
|
|
@@ -146,7 +146,7 @@ module GraphQL
|
|
|
146
146
|
elsif obj.is_a?(Date) || obj.is_a?(Time)
|
|
147
147
|
# DateTime extends Date; for TimeWithZone, call `.utc` first.
|
|
148
148
|
{ TIMESTAMP_KEY => [obj.class.name, obj.strftime(TIMESTAMP_FORMAT)] }
|
|
149
|
-
elsif obj.is_a?(OpenStruct)
|
|
149
|
+
elsif defined?(OpenStruct) && obj.is_a?(OpenStruct)
|
|
150
150
|
{ OPEN_STRUCT_KEY => dump_value(obj.to_h) }
|
|
151
151
|
elsif defined?(ActiveRecord::Relation) && obj.is_a?(ActiveRecord::Relation)
|
|
152
152
|
dump_value(obj.to_a)
|
|
@@ -64,12 +64,12 @@ module GraphQL
|
|
|
64
64
|
event_name = event_name.to_s
|
|
65
65
|
|
|
66
66
|
# Try with the verbatim input first:
|
|
67
|
-
field =
|
|
67
|
+
field = dummy_query.types.field(@schema.subscription, event_name) # rubocop:disable Development/ContextIsPassedCop
|
|
68
68
|
|
|
69
69
|
if field.nil?
|
|
70
70
|
# And if it wasn't found, normalize it:
|
|
71
71
|
normalized_event_name = normalize_name(event_name)
|
|
72
|
-
field =
|
|
72
|
+
field = dummy_query.types.field(@schema.subscription, normalized_event_name) # rubocop:disable Development/ContextIsPassedCop
|
|
73
73
|
if field.nil?
|
|
74
74
|
raise InvalidTriggerError, "No subscription matching trigger: #{event_name} (looked for #{@schema.subscription.graphql_name}.#{normalized_event_name})"
|
|
75
75
|
end
|
|
@@ -235,7 +235,7 @@ module GraphQL
|
|
|
235
235
|
if !query.valid?
|
|
236
236
|
raise "Invalid query: #{query.validation_errors.map(&:to_h).inspect}"
|
|
237
237
|
end
|
|
238
|
-
GraphQL::Analysis
|
|
238
|
+
GraphQL::Analysis.analyze_query(query, @schema.query_analyzers)
|
|
239
239
|
query.context.namespace(:subscriptions)[:subscription_broadcastable]
|
|
240
240
|
end
|
|
241
241
|
|
|
@@ -250,6 +250,8 @@ module GraphQL
|
|
|
250
250
|
def normalize_arguments(event_name, arg_owner, args, context)
|
|
251
251
|
case arg_owner
|
|
252
252
|
when GraphQL::Schema::Field, Class
|
|
253
|
+
return args if args.nil?
|
|
254
|
+
|
|
253
255
|
if arg_owner.is_a?(Class) && !arg_owner.kind.input_object?
|
|
254
256
|
# it's a type, but not an input object
|
|
255
257
|
return args
|
|
@@ -289,7 +291,7 @@ module GraphQL
|
|
|
289
291
|
end
|
|
290
292
|
end
|
|
291
293
|
|
|
292
|
-
if missing_arg_names.
|
|
294
|
+
if !missing_arg_names.empty?
|
|
293
295
|
arg_owner_name = if arg_owner.is_a?(GraphQL::Schema::Field)
|
|
294
296
|
arg_owner.path
|
|
295
297
|
elsif arg_owner.is_a?(Class)
|
|
@@ -302,7 +304,7 @@ module GraphQL
|
|
|
302
304
|
|
|
303
305
|
normalized_args
|
|
304
306
|
when GraphQL::Schema::List
|
|
305
|
-
args
|
|
307
|
+
args&.map { |a| normalize_arguments(event_name, arg_owner.of_type, a, context) }
|
|
306
308
|
when GraphQL::Schema::NonNull
|
|
307
309
|
normalize_arguments(event_name, arg_owner.of_type, args, context)
|
|
308
310
|
else
|
|
@@ -39,24 +39,50 @@ module GraphQL
|
|
|
39
39
|
end
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
-
def run_graphql_field(schema, field_path, object, arguments: {}, context: {})
|
|
42
|
+
def run_graphql_field(schema, field_path, object, arguments: {}, context: {}, ast_node: nil, lookahead: nil, visibility_profile: nil)
|
|
43
43
|
type_name, *field_names = field_path.split(".")
|
|
44
|
-
dummy_query = GraphQL::Query.new(schema, context: context)
|
|
44
|
+
dummy_query = GraphQL::Query.new(schema, "{ __typename }", context: context, visibility_profile: visibility_profile)
|
|
45
45
|
query_context = dummy_query.context
|
|
46
|
-
|
|
46
|
+
dataloader = query_context.dataloader
|
|
47
|
+
object_type = dummy_query.types.type(type_name) # rubocop:disable Development/ContextIsPassedCop
|
|
47
48
|
if object_type
|
|
48
49
|
graphql_result = object
|
|
49
50
|
field_names.each do |field_name|
|
|
50
51
|
inner_object = graphql_result
|
|
51
|
-
|
|
52
|
+
dataloader.run_isolated {
|
|
53
|
+
graphql_result = object_type.wrap(inner_object, query_context)
|
|
54
|
+
}
|
|
52
55
|
if graphql_result.nil?
|
|
53
56
|
return nil
|
|
54
57
|
end
|
|
55
|
-
visible_field = dummy_query.
|
|
58
|
+
visible_field = dummy_query.types.field(object_type, field_name) # rubocop:disable Development/ContextIsPassedCop
|
|
56
59
|
if visible_field
|
|
57
|
-
|
|
60
|
+
dataloader.run_isolated {
|
|
61
|
+
query_context[:current_field] = visible_field
|
|
58
62
|
field_args = visible_field.coerce_arguments(graphql_result, arguments, query_context)
|
|
59
63
|
field_args = schema.sync_lazy(field_args)
|
|
64
|
+
if !visible_field.extras.empty?
|
|
65
|
+
extra_args = {}
|
|
66
|
+
visible_field.extras.each do |extra|
|
|
67
|
+
extra_args[extra] = case extra
|
|
68
|
+
when :ast_node
|
|
69
|
+
ast_node ||= GraphQL::Language::Nodes::Field.new(name: visible_field.graphql_name)
|
|
70
|
+
when :lookahead
|
|
71
|
+
lookahead ||= begin
|
|
72
|
+
ast_node ||= GraphQL::Language::Nodes::Field.new(name: visible_field.graphql_name)
|
|
73
|
+
Execution::Lookahead.new(
|
|
74
|
+
query: dummy_query,
|
|
75
|
+
ast_nodes: [ast_node],
|
|
76
|
+
field: visible_field,
|
|
77
|
+
)
|
|
78
|
+
end
|
|
79
|
+
else
|
|
80
|
+
raise ArgumentError, "This extra isn't supported in `run_graphql_field` yet: `#{extra.inspect}`. Open an issue on GitHub to request it: https://github.com/rmosolgo/graphql-ruby/issues/new"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
field_args = field_args.merge_extras(extra_args)
|
|
85
|
+
end
|
|
60
86
|
graphql_result = visible_field.resolve(graphql_result, field_args.keyword_arguments, query_context)
|
|
61
87
|
graphql_result = schema.sync_lazy(graphql_result)
|
|
62
88
|
}
|
|
@@ -68,39 +94,45 @@ module GraphQL
|
|
|
68
94
|
end
|
|
69
95
|
end
|
|
70
96
|
graphql_result
|
|
71
|
-
elsif schema.has_defined_type?(type_name)
|
|
72
|
-
raise TypeNotVisibleError.new(type_name: type_name)
|
|
73
97
|
else
|
|
74
|
-
|
|
98
|
+
unfiltered_type = schema.use_visibility_profile? ? schema.visibility.get_type(type_name) : schema.get_type(type_name) # rubocop:disable Development/ContextIsPassedCop
|
|
99
|
+
if unfiltered_type
|
|
100
|
+
raise TypeNotVisibleError.new(type_name: type_name)
|
|
101
|
+
else
|
|
102
|
+
raise TypeNotDefinedError.new(type_name: type_name)
|
|
103
|
+
end
|
|
75
104
|
end
|
|
76
105
|
end
|
|
77
106
|
|
|
78
|
-
def with_resolution_context(schema, type:, object:, context:{})
|
|
107
|
+
def with_resolution_context(schema, type:, object:, context:{}, visibility_profile: nil)
|
|
79
108
|
resolution_context = ResolutionAssertionContext.new(
|
|
80
109
|
self,
|
|
81
110
|
schema: schema,
|
|
82
111
|
type_name: type,
|
|
83
112
|
object: object,
|
|
84
|
-
context: context
|
|
113
|
+
context: context,
|
|
114
|
+
visibility_profile: visibility_profile,
|
|
85
115
|
)
|
|
86
116
|
yield(resolution_context)
|
|
87
117
|
end
|
|
88
118
|
|
|
89
119
|
class ResolutionAssertionContext
|
|
90
|
-
def initialize(test, type_name:, object:, schema:, context:)
|
|
120
|
+
def initialize(test, type_name:, object:, schema:, context:, visibility_profile:)
|
|
91
121
|
@test = test
|
|
92
122
|
@type_name = type_name
|
|
93
123
|
@object = object
|
|
94
124
|
@schema = schema
|
|
95
125
|
@context = context
|
|
126
|
+
@visibility_profile = visibility_profile
|
|
96
127
|
end
|
|
97
128
|
|
|
129
|
+
attr_reader :visibility_profile
|
|
98
130
|
|
|
99
131
|
def run_graphql_field(field_name, arguments: {})
|
|
100
132
|
if @schema
|
|
101
|
-
@test.run_graphql_field(@schema, "#{@type_name}.#{field_name}", @object, arguments: arguments, context: @context)
|
|
133
|
+
@test.run_graphql_field(@schema, "#{@type_name}.#{field_name}", @object, arguments: arguments, context: @context, visibility_profile: @visibility_profile)
|
|
102
134
|
else
|
|
103
|
-
@test.run_graphql_field("#{@type_name}.#{field_name}", @object, arguments: arguments, context: @context)
|
|
135
|
+
@test.run_graphql_field("#{@type_name}.#{field_name}", @object, arguments: arguments, context: @context, visibility_profile: @visibility_profile)
|
|
104
136
|
end
|
|
105
137
|
end
|
|
106
138
|
end
|
|
@@ -108,8 +140,8 @@ module GraphQL
|
|
|
108
140
|
module SchemaHelpers
|
|
109
141
|
include Helpers
|
|
110
142
|
|
|
111
|
-
def run_graphql_field(field_path, object, arguments: {}, context: {})
|
|
112
|
-
super(@@schema_class_for_helpers, field_path, object, arguments: arguments, context: context)
|
|
143
|
+
def run_graphql_field(field_path, object, arguments: {}, context: {}, visibility_profile: nil)
|
|
144
|
+
super(@@schema_class_for_helpers, field_path, object, arguments: arguments, context: context, visibility_profile: visibility_profile)
|
|
113
145
|
end
|
|
114
146
|
|
|
115
147
|
def with_resolution_context(*args, **kwargs, &block)
|