graphql 2.0.31 → 2.5.18
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/templates/base_mutation.erb +2 -0
- data/lib/generators/graphql/install/templates/mutation_type.erb +2 -0
- data/lib/generators/graphql/install_generator.rb +49 -0
- data/lib/generators/graphql/orm_mutations_base.rb +1 -1
- data/lib/generators/graphql/templates/base_argument.erb +2 -0
- data/lib/generators/graphql/templates/base_connection.erb +2 -0
- data/lib/generators/graphql/templates/base_edge.erb +2 -0
- data/lib/generators/graphql/templates/base_enum.erb +2 -0
- data/lib/generators/graphql/templates/base_field.erb +2 -0
- data/lib/generators/graphql/templates/base_input_object.erb +2 -0
- data/lib/generators/graphql/templates/base_interface.erb +2 -0
- data/lib/generators/graphql/templates/base_object.erb +2 -0
- data/lib/generators/graphql/templates/base_resolver.erb +8 -0
- data/lib/generators/graphql/templates/base_scalar.erb +2 -0
- data/lib/generators/graphql/templates/base_union.erb +2 -0
- data/lib/generators/graphql/templates/graphql_controller.erb +2 -0
- data/lib/generators/graphql/templates/loader.erb +2 -0
- data/lib/generators/graphql/templates/mutation.erb +2 -0
- data/lib/generators/graphql/templates/node_type.erb +2 -0
- data/lib/generators/graphql/templates/query_type.erb +2 -0
- data/lib/generators/graphql/templates/schema.erb +5 -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/query_depth.rb +58 -0
- 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/coercion_error.rb +1 -9
- 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 +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 +161 -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 +112 -0
- data/lib/graphql/dataloader/null_dataloader.rb +51 -10
- data/lib/graphql/dataloader/request.rb +5 -0
- data/lib/graphql/dataloader/source.rb +35 -12
- data/lib/graphql/dataloader.rb +224 -149
- data/lib/graphql/date_encoding_error.rb +1 -1
- data/lib/graphql/dig.rb +2 -1
- data/lib/graphql/duration_encoding_error.rb +16 -0
- data/lib/graphql/execution/interpreter/argument_value.rb +5 -1
- data/lib/graphql/execution/interpreter/arguments_cache.rb +5 -10
- data/lib/graphql/execution/interpreter/resolve.rb +23 -25
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +228 -0
- data/lib/graphql/execution/interpreter/runtime.rb +363 -434
- data/lib/graphql/execution/interpreter.rb +91 -164
- data/lib/graphql/execution/lookahead.rb +105 -31
- 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/dynamic_fields.rb +1 -1
- data/lib/graphql/introspection/entry_points.rb +11 -5
- data/lib/graphql/introspection/field_type.rb +1 -1
- data/lib/graphql/introspection/schema_type.rb +8 -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/block_string.rb +34 -18
- data/lib/graphql/language/cache.rb +13 -0
- data/lib/graphql/language/comment.rb +18 -0
- data/lib/graphql/language/definition_slice.rb +1 -1
- data/lib/graphql/language/document_from_schema_definition.rb +90 -61
- data/lib/graphql/language/lexer.rb +319 -193
- data/lib/graphql/language/nodes.rb +139 -77
- data/lib/graphql/language/parser.rb +807 -1985
- data/lib/graphql/language/printer.rb +324 -151
- data/lib/graphql/language/sanitized_printer.rb +21 -23
- data/lib/graphql/language/static_visitor.rb +171 -0
- data/lib/graphql/language/visitor.rb +62 -119
- data/lib/graphql/language.rb +71 -1
- data/lib/graphql/load_application_object_failed_error.rb +5 -1
- data/lib/graphql/pagination/array_connection.rb +6 -6
- data/lib/graphql/pagination/connection.rb +28 -1
- data/lib/graphql/pagination/mongoid_relation_connection.rb +1 -2
- data/lib/graphql/query/context/scoped_context.rb +101 -0
- data/lib/graphql/query/context.rb +81 -144
- data/lib/graphql/query/null_context.rb +7 -16
- data/lib/graphql/query/partial.rb +179 -0
- data/lib/graphql/query/validation_pipeline.rb +4 -4
- data/lib/graphql/query/variable_validation_error.rb +1 -1
- data/lib/graphql/query/variables.rb +3 -3
- data/lib/graphql/query.rb +126 -81
- data/lib/graphql/railtie.rb +16 -6
- data/lib/graphql/rake_task.rb +3 -12
- 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 +73 -14
- data/lib/graphql/schema/base_64_encoder.rb +3 -5
- data/lib/graphql/schema/build_from_definition.rb +123 -66
- data/lib/graphql/schema/directive/flagged.rb +4 -2
- data/lib/graphql/schema/directive/one_of.rb +12 -0
- data/lib/graphql/schema/directive/specified_by.rb +14 -0
- data/lib/graphql/schema/directive.rb +55 -3
- data/lib/graphql/schema/enum.rb +110 -27
- data/lib/graphql/schema/enum_value.rb +11 -3
- data/lib/graphql/schema/field/connection_extension.rb +2 -16
- data/lib/graphql/schema/field/scope_extension.rb +8 -1
- data/lib/graphql/schema/field.rb +173 -119
- data/lib/graphql/schema/field_extension.rb +1 -1
- data/lib/graphql/schema/has_single_input_argument.rb +160 -0
- data/lib/graphql/schema/input_object.rb +123 -65
- data/lib/graphql/schema/interface.rb +34 -16
- data/lib/graphql/schema/introspection_system.rb +8 -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 -4
- data/lib/graphql/schema/member/base_dsl_methods.rb +17 -1
- data/lib/graphql/schema/member/has_arguments.rb +132 -100
- 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 +5 -5
- data/lib/graphql/schema/member/has_fields.rb +111 -16
- data/lib/graphql/schema/member/has_interfaces.rb +27 -13
- 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/scoped.rb +19 -0
- data/lib/graphql/schema/member/type_system_helpers.rb +18 -5
- data/lib/graphql/schema/member/validates_input.rb +3 -3
- data/lib/graphql/schema/member.rb +1 -0
- data/lib/graphql/schema/mutation.rb +7 -0
- data/lib/graphql/schema/object.rb +33 -8
- data/lib/graphql/schema/printer.rb +9 -7
- data/lib/graphql/schema/ractor_shareable.rb +79 -0
- data/lib/graphql/schema/relay_classic_mutation.rb +6 -129
- data/lib/graphql/schema/resolver.rb +45 -31
- data/lib/graphql/schema/scalar.rb +4 -9
- data/lib/graphql/schema/subscription.rb +63 -10
- data/lib/graphql/schema/timeout.rb +19 -2
- data/lib/graphql/schema/type_expression.rb +2 -2
- data/lib/graphql/schema/union.rb +2 -2
- data/lib/graphql/schema/unique_within_type.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 +275 -103
- data/lib/graphql/schema.rb +924 -210
- data/lib/graphql/static_validation/all_rules.rb +3 -3
- data/lib/graphql/static_validation/base_visitor.rb +7 -6
- data/lib/graphql/static_validation/literal_validator.rb +6 -7
- 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 +5 -5
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +5 -5
- 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 +21 -5
- data/lib/graphql/static_validation/validator.rb +9 -1
- data/lib/graphql/static_validation.rb +0 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +8 -5
- 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 +21 -4
- data/lib/graphql/subscriptions/serialize.rb +3 -1
- data/lib/graphql/subscriptions.rb +21 -17
- data/lib/graphql/testing/helpers.rb +161 -0
- data/lib/graphql/testing/mock_action_cable.rb +111 -0
- data/lib/graphql/testing.rb +3 -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 +11 -3
- data/lib/graphql/tracing/appoptics_tracing.rb +9 -2
- 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/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 +75 -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 +818 -0
- data/lib/graphql/tracing/platform_trace.rb +5 -0
- data/lib/graphql/tracing/platform_tracing.rb +3 -1
- data/lib/graphql/tracing/{prometheus_tracing → prometheus_trace}/graphql_collector.rb +5 -1
- 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 +82 -0
- data/lib/graphql/tracing/statsd_trace.rb +33 -41
- data/lib/graphql/tracing/statsd_tracing.rb +2 -0
- data/lib/graphql/tracing/trace.rb +112 -1
- data/lib/graphql/tracing.rb +31 -28
- data/lib/graphql/type_kinds.rb +2 -1
- data/lib/graphql/types/iso_8601_duration.rb +77 -0
- data/lib/graphql/types/relay/connection_behaviors.rb +43 -3
- data/lib/graphql/types/relay/edge_behaviors.rb +18 -1
- data/lib/graphql/types/relay/page_info_behaviors.rb +4 -0
- data/lib/graphql/types.rb +18 -10
- data/lib/graphql/unauthorized_enum_value_error.rb +13 -0
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +68 -54
- data/readme.md +12 -2
- metadata +220 -40
- data/lib/graphql/analysis/ast/analyzer.rb +0 -84
- data/lib/graphql/analysis/ast/field_usage.rb +0 -57
- data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -22
- data/lib/graphql/analysis/ast/max_query_depth.rb +0 -22
- data/lib/graphql/analysis/ast/query_complexity.rb +0 -230
- data/lib/graphql/analysis/ast/query_depth.rb +0 -55
- data/lib/graphql/analysis/ast/visitor.rb +0 -276
- data/lib/graphql/analysis/ast.rb +0 -81
- data/lib/graphql/backtrace/inspect_result.rb +0 -50
- data/lib/graphql/backtrace/trace.rb +0 -96
- data/lib/graphql/backtrace/tracer.rb +0 -80
- data/lib/graphql/deprecation.rb +0 -9
- data/lib/graphql/filter.rb +0 -59
- data/lib/graphql/language/parser.y +0 -560
- data/lib/graphql/language/token.rb +0 -34
- data/lib/graphql/schema/base_64_bp.rb +0 -26
- data/lib/graphql/schema/invalid_type_error.rb +0 -7
- data/lib/graphql/schema/null_mask.rb +0 -11
- data/lib/graphql/static_validation/rules/subscription_root_exists.rb +0 -17
- data/lib/graphql/static_validation/type_stack.rb +0 -216
- data/lib/graphql/subscriptions/instrumentation.rb +0 -28
|
@@ -10,6 +10,14 @@ module GraphQL
|
|
|
10
10
|
|
|
11
11
|
include GraphQL::Dig
|
|
12
12
|
|
|
13
|
+
# Raised when an InputObject doesn't have any arguments defined and hasn't explicitly opted out of this requirement
|
|
14
|
+
class ArgumentsAreRequiredError < GraphQL::Error
|
|
15
|
+
def initialize(input_object_type)
|
|
16
|
+
message = "Input Object types must have arguments, but #{input_object_type.graphql_name} doesn't have any. Define an argument for this type, remove it from your schema, or add `has_no_arguments(true)` to its definition."
|
|
17
|
+
super(message)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
13
21
|
# @return [GraphQL::Query::Context] The context for this query
|
|
14
22
|
attr_reader :context
|
|
15
23
|
# @return [GraphQL::Execution::Interpereter::Arguments] The underlying arguments instance
|
|
@@ -23,13 +31,14 @@ module GraphQL
|
|
|
23
31
|
@ruby_style_hash = ruby_kwargs
|
|
24
32
|
@arguments = arguments
|
|
25
33
|
# Apply prepares, not great to have it duplicated here.
|
|
26
|
-
self.class.arguments(context).each_value
|
|
34
|
+
arg_defns = context ? context.types.arguments(self.class) : self.class.arguments(context).each_value
|
|
35
|
+
arg_defns.each do |arg_defn|
|
|
27
36
|
ruby_kwargs_key = arg_defn.keyword
|
|
28
37
|
if @ruby_style_hash.key?(ruby_kwargs_key)
|
|
29
38
|
# Weirdly, procs are applied during coercion, but not methods.
|
|
30
39
|
# Probably because these methods require a `self`.
|
|
31
40
|
if arg_defn.prepare.is_a?(Symbol) || context.nil?
|
|
32
|
-
prepared_value = arg_defn.prepare_value(self, @ruby_style_hash[ruby_kwargs_key])
|
|
41
|
+
prepared_value = arg_defn.prepare_value(self, @ruby_style_hash[ruby_kwargs_key], context: context)
|
|
33
42
|
overwrite_argument(ruby_kwargs_key, prepared_value)
|
|
34
43
|
end
|
|
35
44
|
end
|
|
@@ -44,42 +53,18 @@ module GraphQL
|
|
|
44
53
|
to_h
|
|
45
54
|
end
|
|
46
55
|
|
|
47
|
-
def
|
|
48
|
-
if
|
|
49
|
-
|
|
50
|
-
# Pass this object's class with `as` so that messages are rendered correctly from inherited validators
|
|
51
|
-
Schema::Validator.validate!(self.class.validators, object, @context, @ruby_style_hash, as: self.class)
|
|
52
|
-
self
|
|
56
|
+
def deconstruct_keys(keys = nil)
|
|
57
|
+
if keys.nil?
|
|
58
|
+
@ruby_style_hash
|
|
53
59
|
else
|
|
54
|
-
|
|
60
|
+
new_h = {}
|
|
61
|
+
keys.each { |k| @ruby_style_hash.key?(k) && new_h[k] = @ruby_style_hash[k] }
|
|
62
|
+
new_h
|
|
55
63
|
end
|
|
56
64
|
end
|
|
57
65
|
|
|
58
|
-
def
|
|
59
|
-
|
|
60
|
-
if value.respond_to?(:key?)
|
|
61
|
-
arguments(ctx).each do |_name, input_obj_arg|
|
|
62
|
-
if value.key?(input_obj_arg.keyword) &&
|
|
63
|
-
!input_obj_arg.authorized?(obj, value[input_obj_arg.keyword], ctx)
|
|
64
|
-
return false
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
# It didn't early-return false:
|
|
69
|
-
true
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def self.one_of
|
|
73
|
-
if !one_of?
|
|
74
|
-
if all_argument_definitions.any? { |arg| arg.type.non_null? }
|
|
75
|
-
raise ArgumentError, "`one_of` may not be used with required arguments -- add `required: false` to argument definitions to use `one_of`"
|
|
76
|
-
end
|
|
77
|
-
directive(GraphQL::Schema::Directive::OneOf)
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def self.one_of?
|
|
82
|
-
directives.any? { |d| d.is_a?(GraphQL::Schema::Directive::OneOf) }
|
|
66
|
+
def prepare
|
|
67
|
+
self
|
|
83
68
|
end
|
|
84
69
|
|
|
85
70
|
def unwrap_value(value)
|
|
@@ -119,7 +104,42 @@ module GraphQL
|
|
|
119
104
|
@ruby_style_hash.dup
|
|
120
105
|
end
|
|
121
106
|
|
|
107
|
+
# @api private
|
|
108
|
+
def validate_for(context)
|
|
109
|
+
object = context[:current_object]
|
|
110
|
+
# Pass this object's class with `as` so that messages are rendered correctly from inherited validators
|
|
111
|
+
Schema::Validator.validate!(self.class.validators, object, context, @ruby_style_hash, as: self.class)
|
|
112
|
+
nil
|
|
113
|
+
end
|
|
114
|
+
|
|
122
115
|
class << self
|
|
116
|
+
def authorized?(obj, value, ctx)
|
|
117
|
+
# Authorize each argument (but this doesn't apply if `prepare` is implemented):
|
|
118
|
+
if value.respond_to?(:key?)
|
|
119
|
+
ctx.types.arguments(self).each do |input_obj_arg|
|
|
120
|
+
if value.key?(input_obj_arg.keyword) &&
|
|
121
|
+
!input_obj_arg.authorized?(obj, value[input_obj_arg.keyword], ctx)
|
|
122
|
+
return false
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
# It didn't early-return false:
|
|
127
|
+
true
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def one_of
|
|
131
|
+
if !one_of?
|
|
132
|
+
if all_argument_definitions.any? { |arg| arg.type.non_null? }
|
|
133
|
+
raise ArgumentError, "`one_of` may not be used with required arguments -- add `required: false` to argument definitions to use `one_of`"
|
|
134
|
+
end
|
|
135
|
+
directive(GraphQL::Schema::Directive::OneOf)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def one_of?
|
|
140
|
+
false # Re-defined when `OneOf` is added
|
|
141
|
+
end
|
|
142
|
+
|
|
123
143
|
def argument(*args, **kwargs, &block)
|
|
124
144
|
argument_defn = super(*args, **kwargs, &block)
|
|
125
145
|
if one_of?
|
|
@@ -131,12 +151,9 @@ module GraphQL
|
|
|
131
151
|
end
|
|
132
152
|
end
|
|
133
153
|
# Add a method access
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
self[#{method_name.inspect}]
|
|
138
|
-
end
|
|
139
|
-
RUBY
|
|
154
|
+
suppress_redefinition_warning do
|
|
155
|
+
define_accessor_method(argument_defn.keyword)
|
|
156
|
+
end
|
|
140
157
|
argument_defn
|
|
141
158
|
end
|
|
142
159
|
|
|
@@ -145,10 +162,10 @@ module GraphQL
|
|
|
145
162
|
end
|
|
146
163
|
|
|
147
164
|
# @api private
|
|
148
|
-
INVALID_OBJECT_MESSAGE = "Expected %{object} to be a key-value object
|
|
165
|
+
INVALID_OBJECT_MESSAGE = "Expected %{object} to be a key-value object."
|
|
149
166
|
|
|
150
167
|
def validate_non_null_input(input, ctx, max_errors: nil)
|
|
151
|
-
|
|
168
|
+
types = ctx.types
|
|
152
169
|
|
|
153
170
|
if input.is_a?(Array)
|
|
154
171
|
return GraphQL::Query::InputValidationResult.from_problem(INVALID_OBJECT_MESSAGE % { object: JSON.generate(input, quirks_mode: true) })
|
|
@@ -159,30 +176,37 @@ module GraphQL
|
|
|
159
176
|
return GraphQL::Query::InputValidationResult.from_problem(INVALID_OBJECT_MESSAGE % { object: JSON.generate(input, quirks_mode: true) })
|
|
160
177
|
end
|
|
161
178
|
|
|
162
|
-
# Inject missing required arguments
|
|
163
|
-
missing_required_inputs = self.arguments(ctx).reduce({}) do |m, (argument_name, argument)|
|
|
164
|
-
if !input.key?(argument_name) && argument.type.non_null? && warden.get_argument(self, argument_name)
|
|
165
|
-
m[argument_name] = nil
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
m
|
|
169
|
-
end
|
|
170
179
|
|
|
171
180
|
result = nil
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
input.each do |argument_name, value|
|
|
184
|
+
argument = types.argument(self, argument_name)
|
|
185
|
+
if argument.nil? && ctx.is_a?(Query::NullContext) && argument_name.is_a?(Symbol)
|
|
186
|
+
# Validating definition directive arguments which come in as Symbols
|
|
187
|
+
argument = types.arguments(self).find { |arg| arg.keyword == argument_name }
|
|
188
|
+
end
|
|
189
|
+
# Items in the input that are unexpected
|
|
190
|
+
if argument.nil?
|
|
191
|
+
result ||= Query::InputValidationResult.new
|
|
192
|
+
result.add_problem("Field is not defined on #{self.graphql_name}", [argument_name])
|
|
193
|
+
else
|
|
194
|
+
# Items in the input that are expected, but have invalid values
|
|
195
|
+
argument_result = argument.type.validate_input(value, ctx)
|
|
196
|
+
if !argument_result.valid?
|
|
182
197
|
result ||= Query::InputValidationResult.new
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
198
|
+
result.merge_result!(argument_name, argument_result)
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# Check for missing non-null arguments
|
|
204
|
+
ctx.types.arguments(self).each do |argument|
|
|
205
|
+
if !input.key?(argument.graphql_name) && argument.type.non_null? && !argument.default_value?
|
|
206
|
+
result ||= Query::InputValidationResult.new
|
|
207
|
+
argument_result = argument.type.validate_input(nil, ctx)
|
|
208
|
+
if !argument_result.valid?
|
|
209
|
+
result.merge_result!(argument.graphql_name, argument_result)
|
|
186
210
|
end
|
|
187
211
|
end
|
|
188
212
|
end
|
|
@@ -215,8 +239,7 @@ module GraphQL
|
|
|
215
239
|
if resolved_arguments.is_a?(GraphQL::Error)
|
|
216
240
|
raise resolved_arguments
|
|
217
241
|
else
|
|
218
|
-
|
|
219
|
-
input_obj_instance.prepare
|
|
242
|
+
self.new(resolved_arguments, ruby_kwargs: resolved_arguments.keyword_arguments, context: ctx, defaults_used: nil)
|
|
220
243
|
end
|
|
221
244
|
end
|
|
222
245
|
end
|
|
@@ -242,6 +265,41 @@ module GraphQL
|
|
|
242
265
|
|
|
243
266
|
result
|
|
244
267
|
end
|
|
268
|
+
|
|
269
|
+
# @param new_has_no_arguments [Boolean] Call with `true` to make this InputObject type ignore the requirement to have any defined arguments.
|
|
270
|
+
# @return [void]
|
|
271
|
+
def has_no_arguments(new_has_no_arguments)
|
|
272
|
+
@has_no_arguments = new_has_no_arguments
|
|
273
|
+
nil
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
# @return [Boolean] `true` if `has_no_arguments(true)` was configued
|
|
277
|
+
def has_no_arguments?
|
|
278
|
+
@has_no_arguments
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def arguments(context = GraphQL::Query::NullContext.instance, require_defined_arguments = true)
|
|
282
|
+
if require_defined_arguments && !has_no_arguments? && !any_arguments?
|
|
283
|
+
warn(GraphQL::Schema::InputObject::ArgumentsAreRequiredError.new(self).message + "\n\nThis will raise an error in a future GraphQL-Ruby version.")
|
|
284
|
+
end
|
|
285
|
+
super(context, false)
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
private
|
|
289
|
+
|
|
290
|
+
# Suppress redefinition warning for objectId arguments
|
|
291
|
+
def suppress_redefinition_warning
|
|
292
|
+
verbose = $VERBOSE
|
|
293
|
+
$VERBOSE = nil
|
|
294
|
+
yield
|
|
295
|
+
ensure
|
|
296
|
+
$VERBOSE = verbose
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
def define_accessor_method(method_name)
|
|
300
|
+
define_method(method_name) { self[method_name] }
|
|
301
|
+
alias_method(method_name, method_name)
|
|
302
|
+
end
|
|
245
303
|
end
|
|
246
304
|
|
|
247
305
|
private
|
|
@@ -13,6 +13,7 @@ module GraphQL
|
|
|
13
13
|
include GraphQL::Schema::Member::Scoped
|
|
14
14
|
include GraphQL::Schema::Member::HasAstNode
|
|
15
15
|
include GraphQL::Schema::Member::HasUnresolvedTypeError
|
|
16
|
+
include GraphQL::Schema::Member::HasDataloader
|
|
16
17
|
include GraphQL::Schema::Member::HasDirectives
|
|
17
18
|
include GraphQL::Schema::Member::HasInterfaces
|
|
18
19
|
|
|
@@ -20,7 +21,16 @@ module GraphQL
|
|
|
20
21
|
# - Added as class methods to this interface
|
|
21
22
|
# - Added as class methods to all child interfaces
|
|
22
23
|
def definition_methods(&block)
|
|
23
|
-
|
|
24
|
+
# Use an instance variable to tell whether it's been included previously or not;
|
|
25
|
+
# You can't use constant detection because constants are brought into scope
|
|
26
|
+
# by `include`, which has already happened at this point.
|
|
27
|
+
if !defined?(@_definition_methods)
|
|
28
|
+
defn_methods_module = Module.new
|
|
29
|
+
@_definition_methods = defn_methods_module
|
|
30
|
+
const_set(:DefinitionMethods, defn_methods_module)
|
|
31
|
+
extend(self::DefinitionMethods)
|
|
32
|
+
end
|
|
33
|
+
self::DefinitionMethods.module_exec(&block)
|
|
24
34
|
end
|
|
25
35
|
|
|
26
36
|
# @see {Schema::Warden} hides interfaces without visible implementations
|
|
@@ -47,22 +57,14 @@ module GraphQL
|
|
|
47
57
|
|
|
48
58
|
child_class.type_membership_class(self.type_membership_class)
|
|
49
59
|
child_class.ancestors.reverse_each do |ancestor|
|
|
50
|
-
if ancestor.const_defined?(:DefinitionMethods)
|
|
60
|
+
if ancestor.const_defined?(:DefinitionMethods) && ancestor != child_class
|
|
51
61
|
child_class.extend(ancestor::DefinitionMethods)
|
|
52
62
|
end
|
|
53
63
|
end
|
|
54
64
|
|
|
55
|
-
# Use an instance variable to tell whether it's been included previously or not;
|
|
56
|
-
# You can't use constant detection because constants are brought into scope
|
|
57
|
-
# by `include`, which has already happened at this point.
|
|
58
|
-
if !child_class.instance_variable_defined?(:@_definition_methods)
|
|
59
|
-
defn_methods_module = Module.new
|
|
60
|
-
child_class.instance_variable_set(:@_definition_methods, defn_methods_module)
|
|
61
|
-
child_class.const_set(:DefinitionMethods, defn_methods_module)
|
|
62
|
-
child_class.extend(child_class::DefinitionMethods)
|
|
63
|
-
end
|
|
64
65
|
child_class.introspection(introspection)
|
|
65
66
|
child_class.description(description)
|
|
67
|
+
child_class.comment(nil)
|
|
66
68
|
# If interfaces are mixed into each other, only define this class once
|
|
67
69
|
if !child_class.const_defined?(:UnresolvedTypeError, false)
|
|
68
70
|
add_unresolved_type_error(child_class)
|
|
@@ -82,13 +84,29 @@ module GraphQL
|
|
|
82
84
|
super
|
|
83
85
|
end
|
|
84
86
|
|
|
87
|
+
# Register other Interface or Object types as implementers of this Interface.
|
|
88
|
+
#
|
|
89
|
+
# When those Interfaces or Objects aren't used as the return values of fields,
|
|
90
|
+
# they may have to be registered using this method so that GraphQL-Ruby can find them.
|
|
91
|
+
# @param types [Class, Module]
|
|
92
|
+
# @return [Array<Module, Class>] Implementers of this interface, if they're registered
|
|
85
93
|
def orphan_types(*types)
|
|
86
|
-
if types.
|
|
87
|
-
@orphan_types
|
|
94
|
+
if !types.empty?
|
|
95
|
+
@orphan_types ||= []
|
|
96
|
+
@orphan_types.concat(types)
|
|
88
97
|
else
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
98
|
+
if defined?(@orphan_types)
|
|
99
|
+
all_orphan_types = @orphan_types.dup
|
|
100
|
+
if defined?(super)
|
|
101
|
+
all_orphan_types += super
|
|
102
|
+
all_orphan_types.uniq!
|
|
103
|
+
end
|
|
104
|
+
all_orphan_types
|
|
105
|
+
elsif defined?(super)
|
|
106
|
+
super
|
|
107
|
+
else
|
|
108
|
+
EmptyObjects::EMPTY_ARRAY
|
|
109
|
+
end
|
|
92
110
|
end
|
|
93
111
|
end
|
|
94
112
|
|
|
@@ -25,10 +25,10 @@ module GraphQL
|
|
|
25
25
|
load_constant(:DirectiveLocationEnum)
|
|
26
26
|
]
|
|
27
27
|
@types = {}
|
|
28
|
-
@possible_types = {}
|
|
28
|
+
@possible_types = {}.compare_by_identity
|
|
29
29
|
type_defns.each do |t|
|
|
30
30
|
@types[t.graphql_name] = t
|
|
31
|
-
@possible_types[t
|
|
31
|
+
@possible_types[t] = [t]
|
|
32
32
|
end
|
|
33
33
|
@entry_point_fields =
|
|
34
34
|
if schema.disable_introspection_entry_points?
|
|
@@ -39,7 +39,9 @@ module GraphQL
|
|
|
39
39
|
entry_point_fields.delete('__type') if schema.disable_type_introspection_entry_point?
|
|
40
40
|
entry_point_fields
|
|
41
41
|
end
|
|
42
|
+
@entry_point_fields.each { |k, v| v.dynamic_introspection = true }
|
|
42
43
|
@dynamic_fields = get_fields_from_class(class_sym: :DynamicFields)
|
|
44
|
+
@dynamic_fields.each { |k, v| v.dynamic_introspection = true }
|
|
43
45
|
end
|
|
44
46
|
|
|
45
47
|
def entry_points
|
|
@@ -67,7 +69,7 @@ module GraphQL
|
|
|
67
69
|
def resolve_late_bindings
|
|
68
70
|
@types.each do |name, t|
|
|
69
71
|
if t.kind.fields?
|
|
70
|
-
t.
|
|
72
|
+
t.all_field_definitions.each do |field_defn|
|
|
71
73
|
field_defn.type = resolve_late_binding(field_defn.type)
|
|
72
74
|
end
|
|
73
75
|
end
|
|
@@ -88,7 +90,8 @@ module GraphQL
|
|
|
88
90
|
def resolve_late_binding(late_bound_type)
|
|
89
91
|
case late_bound_type
|
|
90
92
|
when GraphQL::Schema::LateBoundType
|
|
91
|
-
|
|
93
|
+
type_name = late_bound_type.name
|
|
94
|
+
@types[type_name] || @schema.get_type(type_name)
|
|
92
95
|
when GraphQL::Schema::List
|
|
93
96
|
resolve_late_binding(late_bound_type.of_type).to_list_type
|
|
94
97
|
when GraphQL::Schema::NonNull
|
|
@@ -111,19 +114,7 @@ module GraphQL
|
|
|
111
114
|
|
|
112
115
|
def get_fields_from_class(class_sym:)
|
|
113
116
|
object_type_defn = load_constant(class_sym)
|
|
114
|
-
|
|
115
|
-
if object_type_defn.is_a?(Module)
|
|
116
|
-
object_type_defn.fields
|
|
117
|
-
else
|
|
118
|
-
extracted_field_defns = {}
|
|
119
|
-
object_class = object_type_defn.metadata[:type_class]
|
|
120
|
-
object_type_defn.all_fields.each do |field_defn|
|
|
121
|
-
inner_resolve = field_defn.resolve_proc
|
|
122
|
-
resolve_with_instantiate = PerFieldProxyResolve.new(object_class: object_class, inner_resolve: inner_resolve)
|
|
123
|
-
extracted_field_defns[field_defn.name] = field_defn.redefine(resolve: resolve_with_instantiate)
|
|
124
|
-
end
|
|
125
|
-
extracted_field_defns
|
|
126
|
-
end
|
|
117
|
+
object_type_defn.fields
|
|
127
118
|
end
|
|
128
119
|
|
|
129
120
|
# This is probably not 100% robust -- but it has to be good enough to avoid modifying the built-in introspection types
|
data/lib/graphql/schema/list.rb
CHANGED
|
@@ -4,7 +4,7 @@ module GraphQL
|
|
|
4
4
|
class Schema
|
|
5
5
|
# Represents a list type in the schema.
|
|
6
6
|
# Wraps a {Schema::Member} as a list type.
|
|
7
|
-
# @see
|
|
7
|
+
# @see Schema::Member::TypeSystemHelpers#to_list_type Create a list type from another GraphQL type
|
|
8
8
|
class List < GraphQL::Schema::Wrapper
|
|
9
9
|
include Schema::Member::ValidatesInput
|
|
10
10
|
|
|
@@ -52,7 +52,7 @@ module GraphQL
|
|
|
52
52
|
unless item_result.valid?
|
|
53
53
|
if max_errors
|
|
54
54
|
if max_errors == 0
|
|
55
|
-
|
|
55
|
+
add_max_errors_reached_message(result)
|
|
56
56
|
break
|
|
57
57
|
end
|
|
58
58
|
|
|
@@ -76,7 +76,7 @@ module GraphQL
|
|
|
76
76
|
end
|
|
77
77
|
end
|
|
78
78
|
|
|
79
|
-
def
|
|
79
|
+
def add_max_errors_reached_message(result)
|
|
80
80
|
message = "Too many errors processing list variable, max validation error limit reached. Execution aborted"
|
|
81
81
|
item_result = GraphQL::Query::InputValidationResult.from_problem(message)
|
|
82
82
|
result.merge_result!(nil, item_result)
|
|
@@ -32,7 +32,8 @@ module GraphQL
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
Class.new(GraphQL::Schema) do
|
|
35
|
-
|
|
35
|
+
add_type_and_traverse(types.values, root: false)
|
|
36
|
+
orphan_types(types.values.select { |t| t.kind.object? })
|
|
36
37
|
directives(directives)
|
|
37
38
|
description(schema["description"])
|
|
38
39
|
|
|
@@ -176,7 +177,6 @@ module GraphQL
|
|
|
176
177
|
while (of_type = unwrapped_field_hash["ofType"])
|
|
177
178
|
unwrapped_field_hash = of_type
|
|
178
179
|
end
|
|
179
|
-
type_name = unwrapped_field_hash["name"]
|
|
180
180
|
|
|
181
181
|
type_defn.field(
|
|
182
182
|
field_hash["name"],
|
|
@@ -186,9 +186,8 @@ module GraphQL
|
|
|
186
186
|
null: true,
|
|
187
187
|
camelize: false,
|
|
188
188
|
connection_extension: nil,
|
|
189
|
-
connection: type_name.end_with?("Connection"),
|
|
190
189
|
) do
|
|
191
|
-
if field_hash["args"].
|
|
190
|
+
if !field_hash["args"].empty?
|
|
192
191
|
loader.build_arguments(self, field_hash["args"], type_resolver)
|
|
193
192
|
end
|
|
194
193
|
end
|
|
@@ -50,12 +50,27 @@ module GraphQL
|
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
+
# Call this method to provide a new comment; OR
|
|
54
|
+
# call it without an argument to get the comment
|
|
55
|
+
# @param new_comment [String]
|
|
56
|
+
# @return [String, nil]
|
|
57
|
+
def comment(new_comment = NOT_CONFIGURED)
|
|
58
|
+
if !NOT_CONFIGURED.equal?(new_comment)
|
|
59
|
+
@comment = new_comment
|
|
60
|
+
elsif defined?(@comment)
|
|
61
|
+
@comment
|
|
62
|
+
else
|
|
63
|
+
nil
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
53
67
|
# This pushes some configurations _down_ the inheritance tree,
|
|
54
68
|
# in order to prevent repetitive lookups at runtime.
|
|
55
69
|
module ConfigurationExtension
|
|
56
70
|
def inherited(child_class)
|
|
57
71
|
child_class.introspection(introspection)
|
|
58
72
|
child_class.description(description)
|
|
73
|
+
child_class.comment(nil)
|
|
59
74
|
child_class.default_graphql_name = nil
|
|
60
75
|
|
|
61
76
|
if defined?(@graphql_name) && @graphql_name && (self.name.nil? || graphql_name != default_graphql_name)
|
|
@@ -102,7 +117,8 @@ module GraphQL
|
|
|
102
117
|
def default_graphql_name
|
|
103
118
|
@default_graphql_name ||= begin
|
|
104
119
|
raise GraphQL::RequiredImplementationMissingError, 'Anonymous class should declare a `graphql_name`' if name.nil?
|
|
105
|
-
-name.split("::").last
|
|
120
|
+
g_name = -name.split("::").last
|
|
121
|
+
g_name.end_with?("Type") ? g_name.sub(/Type\Z/, "") : g_name
|
|
106
122
|
end
|
|
107
123
|
end
|
|
108
124
|
|