graphql 2.0.13 → 2.3.10
Sign up to get free protection for your applications and to get access to all the features.
- 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 +3 -0
- data/lib/generators/graphql/mutation_delete_generator.rb +1 -1
- data/lib/generators/graphql/mutation_update_generator.rb +1 -1
- data/lib/generators/graphql/relay.rb +18 -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 +6 -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 +8 -0
- data/lib/graphql/analysis/analyzer.rb +89 -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 +183 -0
- data/lib/graphql/analysis/query_depth.rb +58 -0
- data/lib/graphql/analysis/visitor.rb +283 -0
- data/lib/graphql/analysis.rb +92 -1
- data/lib/graphql/backtrace/inspect_result.rb +0 -12
- data/lib/graphql/backtrace/table.rb +2 -2
- data/lib/graphql/backtrace/trace.rb +93 -0
- data/lib/graphql/backtrace/tracer.rb +1 -1
- data/lib/graphql/backtrace.rb +2 -1
- data/lib/graphql/coercion_error.rb +1 -9
- data/lib/graphql/dataloader/async_dataloader.rb +88 -0
- data/lib/graphql/dataloader/null_dataloader.rb +1 -1
- data/lib/graphql/dataloader/request.rb +5 -0
- data/lib/graphql/dataloader/source.rb +89 -45
- data/lib/graphql/dataloader.rb +115 -142
- 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.rb +1 -1
- data/lib/graphql/execution/interpreter/arguments_cache.rb +33 -33
- data/lib/graphql/execution/interpreter/resolve.rb +19 -0
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +175 -0
- data/lib/graphql/execution/interpreter/runtime.rb +331 -455
- data/lib/graphql/execution/interpreter.rb +125 -61
- data/lib/graphql/execution/lazy.rb +6 -12
- data/lib/graphql/execution/lookahead.rb +124 -46
- data/lib/graphql/execution/multiplex.rb +3 -117
- data/lib/graphql/execution.rb +0 -1
- data/lib/graphql/introspection/directive_type.rb +3 -3
- 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 +2 -2
- data/lib/graphql/introspection/schema_type.rb +10 -13
- data/lib/graphql/introspection/type_type.rb +17 -10
- data/lib/graphql/introspection.rb +3 -2
- data/lib/graphql/language/block_string.rb +34 -18
- data/lib/graphql/language/definition_slice.rb +1 -1
- data/lib/graphql/language/document_from_schema_definition.rb +75 -59
- data/lib/graphql/language/lexer.rb +358 -1506
- data/lib/graphql/language/nodes.rb +166 -93
- data/lib/graphql/language/parser.rb +795 -1953
- data/lib/graphql/language/printer.rb +340 -160
- data/lib/graphql/language/sanitized_printer.rb +21 -23
- data/lib/graphql/language/static_visitor.rb +167 -0
- data/lib/graphql/language/visitor.rb +188 -141
- data/lib/graphql/language.rb +61 -1
- data/lib/graphql/load_application_object_failed_error.rb +5 -1
- data/lib/graphql/pagination/active_record_relation_connection.rb +0 -8
- data/lib/graphql/pagination/array_connection.rb +6 -6
- data/lib/graphql/pagination/connection.rb +33 -6
- 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 +117 -112
- data/lib/graphql/query/null_context.rb +12 -25
- data/lib/graphql/query/validation_pipeline.rb +6 -5
- data/lib/graphql/query/variables.rb +3 -3
- data/lib/graphql/query.rb +86 -30
- data/lib/graphql/railtie.rb +9 -6
- data/lib/graphql/rake_task.rb +29 -11
- data/lib/graphql/rubocop/graphql/base_cop.rb +1 -1
- data/lib/graphql/schema/addition.rb +59 -23
- data/lib/graphql/schema/always_visible.rb +11 -0
- data/lib/graphql/schema/argument.rb +55 -26
- data/lib/graphql/schema/base_64_encoder.rb +3 -5
- data/lib/graphql/schema/build_from_definition.rb +56 -32
- data/lib/graphql/schema/directive/one_of.rb +24 -0
- data/lib/graphql/schema/directive/specified_by.rb +14 -0
- data/lib/graphql/schema/directive/transform.rb +1 -1
- data/lib/graphql/schema/directive.rb +15 -3
- data/lib/graphql/schema/enum.rb +35 -24
- data/lib/graphql/schema/enum_value.rb +2 -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 +147 -107
- data/lib/graphql/schema/field_extension.rb +1 -4
- data/lib/graphql/schema/find_inherited_value.rb +2 -7
- data/lib/graphql/schema/has_single_input_argument.rb +158 -0
- data/lib/graphql/schema/input_object.rb +47 -11
- data/lib/graphql/schema/interface.rb +15 -21
- data/lib/graphql/schema/introspection_system.rb +7 -17
- data/lib/graphql/schema/late_bound_type.rb +10 -0
- data/lib/graphql/schema/list.rb +2 -2
- data/lib/graphql/schema/loader.rb +2 -3
- data/lib/graphql/schema/member/base_dsl_methods.rb +18 -14
- data/lib/graphql/schema/member/build_type.rb +11 -3
- data/lib/graphql/schema/member/has_arguments.rb +170 -130
- data/lib/graphql/schema/member/has_ast_node.rb +12 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +3 -4
- data/lib/graphql/schema/member/has_directives.rb +81 -61
- data/lib/graphql/schema/member/has_fields.rb +100 -38
- data/lib/graphql/schema/member/has_interfaces.rb +65 -10
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +5 -1
- data/lib/graphql/schema/member/has_validators.rb +32 -6
- data/lib/graphql/schema/member/relay_shortcuts.rb +19 -0
- data/lib/graphql/schema/member/scoped.rb +19 -0
- data/lib/graphql/schema/member/type_system_helpers.rb +16 -0
- data/lib/graphql/schema/member/validates_input.rb +3 -3
- data/lib/graphql/schema/mutation.rb +7 -0
- data/lib/graphql/schema/object.rb +16 -5
- data/lib/graphql/schema/printer.rb +11 -8
- data/lib/graphql/schema/relay_classic_mutation.rb +7 -129
- data/lib/graphql/schema/resolver/has_payload_type.rb +9 -9
- data/lib/graphql/schema/resolver.rb +47 -32
- data/lib/graphql/schema/scalar.rb +3 -3
- data/lib/graphql/schema/subscription.rb +11 -4
- data/lib/graphql/schema/subset.rb +397 -0
- data/lib/graphql/schema/timeout.rb +25 -29
- data/lib/graphql/schema/type_expression.rb +2 -2
- data/lib/graphql/schema/type_membership.rb +3 -0
- data/lib/graphql/schema/union.rb +11 -2
- data/lib/graphql/schema/unique_within_type.rb +1 -1
- data/lib/graphql/schema/validator/all_validator.rb +60 -0
- data/lib/graphql/schema/validator.rb +4 -2
- data/lib/graphql/schema/warden.rb +238 -93
- data/lib/graphql/schema.rb +498 -103
- data/lib/graphql/static_validation/all_rules.rb +2 -1
- data/lib/graphql/static_validation/base_visitor.rb +7 -6
- data/lib/graphql/static_validation/definition_dependencies.rb +7 -1
- data/lib/graphql/static_validation/literal_validator.rb +24 -7
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +1 -1
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -2
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +12 -4
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +10 -10
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +1 -1
- 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/one_of_input_objects_are_valid.rb +66 -0
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
- data/lib/graphql/static_validation/rules/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 +5 -5
- data/lib/graphql/static_validation/rules/subscription_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +18 -27
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +1 -1
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
- data/lib/graphql/static_validation/validation_context.rb +5 -5
- data/lib/graphql/static_validation/validator.rb +4 -1
- data/lib/graphql/static_validation.rb +0 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +11 -4
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +11 -5
- data/lib/graphql/subscriptions/event.rb +11 -10
- data/lib/graphql/subscriptions/serialize.rb +2 -0
- data/lib/graphql/subscriptions.rb +20 -13
- data/lib/graphql/testing/helpers.rb +151 -0
- data/lib/graphql/testing.rb +2 -0
- data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
- data/lib/graphql/tracing/appoptics_trace.rb +251 -0
- data/lib/graphql/tracing/appoptics_tracing.rb +2 -2
- data/lib/graphql/tracing/appsignal_trace.rb +77 -0
- data/lib/graphql/tracing/data_dog_trace.rb +183 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +9 -21
- data/lib/graphql/{execution/instrumentation.rb → tracing/legacy_hooks_trace.rb} +10 -28
- data/lib/graphql/tracing/legacy_trace.rb +69 -0
- data/lib/graphql/tracing/new_relic_trace.rb +75 -0
- data/lib/graphql/tracing/notifications_trace.rb +45 -0
- data/lib/graphql/tracing/platform_trace.rb +118 -0
- data/lib/graphql/tracing/platform_tracing.rb +17 -3
- data/lib/graphql/tracing/{prometheus_tracing → prometheus_trace}/graphql_collector.rb +4 -2
- data/lib/graphql/tracing/prometheus_trace.rb +89 -0
- data/lib/graphql/tracing/prometheus_tracing.rb +3 -3
- data/lib/graphql/tracing/scout_trace.rb +72 -0
- data/lib/graphql/tracing/sentry_trace.rb +112 -0
- data/lib/graphql/tracing/statsd_trace.rb +56 -0
- data/lib/graphql/tracing/trace.rb +76 -0
- data/lib/graphql/tracing.rb +20 -40
- data/lib/graphql/type_kinds.rb +7 -4
- data/lib/graphql/types/iso_8601_duration.rb +77 -0
- data/lib/graphql/types/relay/base_connection.rb +1 -1
- data/lib/graphql/types/relay/connection_behaviors.rb +68 -6
- data/lib/graphql/types/relay/edge_behaviors.rb +33 -5
- data/lib/graphql/types/relay/node_behaviors.rb +8 -2
- data/lib/graphql/types/relay/page_info_behaviors.rb +11 -2
- data/lib/graphql/types/relay.rb +0 -1
- data/lib/graphql/types/string.rb +1 -1
- data/lib/graphql/types.rb +1 -0
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +27 -20
- data/readme.md +13 -3
- metadata +96 -47
- 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 -269
- data/lib/graphql/analysis/ast.rb +0 -81
- data/lib/graphql/deprecation.rb +0 -9
- data/lib/graphql/filter.rb +0 -53
- data/lib/graphql/language/lexer.rl +0 -280
- data/lib/graphql/language/parser.y +0 -554
- 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/static_validation/type_stack.rb +0 -216
- data/lib/graphql/subscriptions/instrumentation.rb +0 -28
- data/lib/graphql/types/relay/default_relay.rb +0 -21
@@ -0,0 +1,158 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
class Schema
|
5
|
+
module HasSingleInputArgument
|
6
|
+
def resolve_with_support(**inputs)
|
7
|
+
if inputs[:input].is_a?(InputObject)
|
8
|
+
input = inputs[:input].to_kwargs
|
9
|
+
else
|
10
|
+
input = inputs[:input]
|
11
|
+
end
|
12
|
+
|
13
|
+
new_extras = field ? field.extras : []
|
14
|
+
all_extras = self.class.extras + new_extras
|
15
|
+
|
16
|
+
# Transfer these from the top-level hash to the
|
17
|
+
# shortcutted `input:` object
|
18
|
+
all_extras.each do |ext|
|
19
|
+
# It's possible that the `extra` was not passed along by this point,
|
20
|
+
# don't re-add it if it wasn't given here.
|
21
|
+
if inputs.key?(ext)
|
22
|
+
input[ext] = inputs[ext]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
if input
|
27
|
+
# This is handled by Relay::Mutation::Resolve, a bit hacky, but here we are.
|
28
|
+
input_kwargs = input.to_h
|
29
|
+
else
|
30
|
+
# Relay Classic Mutations with no `argument`s
|
31
|
+
# don't require `input:`
|
32
|
+
input_kwargs = {}
|
33
|
+
end
|
34
|
+
|
35
|
+
if input_kwargs.any?
|
36
|
+
super(**input_kwargs)
|
37
|
+
else
|
38
|
+
super()
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.included(base)
|
43
|
+
base.extend(ClassMethods)
|
44
|
+
end
|
45
|
+
|
46
|
+
module ClassMethods
|
47
|
+
def dummy
|
48
|
+
@dummy ||= begin
|
49
|
+
d = Class.new(GraphQL::Schema::Resolver)
|
50
|
+
d.graphql_name "#{self.graphql_name}DummyResolver"
|
51
|
+
d.argument_class(self.argument_class)
|
52
|
+
# TODO make this lazier?
|
53
|
+
d.argument(:input, input_type, description: "Parameters for #{self.graphql_name}")
|
54
|
+
d
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def field_arguments(context = GraphQL::Query::NullContext.instance)
|
59
|
+
dummy.arguments(context)
|
60
|
+
end
|
61
|
+
|
62
|
+
def get_field_argument(name, context = GraphQL::Query::NullContext.instance)
|
63
|
+
dummy.get_argument(name, context)
|
64
|
+
end
|
65
|
+
|
66
|
+
def own_field_arguments
|
67
|
+
dummy.own_arguments
|
68
|
+
end
|
69
|
+
|
70
|
+
def any_field_arguments?
|
71
|
+
dummy.any_arguments?
|
72
|
+
end
|
73
|
+
|
74
|
+
def all_field_argument_definitions
|
75
|
+
dummy.all_argument_definitions
|
76
|
+
end
|
77
|
+
|
78
|
+
# Also apply this argument to the input type:
|
79
|
+
def argument(*args, own_argument: false, **kwargs, &block)
|
80
|
+
it = input_type # make sure any inherited arguments are already added to it
|
81
|
+
arg = super(*args, **kwargs, &block)
|
82
|
+
|
83
|
+
# This definition might be overriding something inherited;
|
84
|
+
# if it is, remove the inherited definition so it's not confused at runtime as having multiple definitions
|
85
|
+
prev_args = it.own_arguments[arg.graphql_name]
|
86
|
+
case prev_args
|
87
|
+
when GraphQL::Schema::Argument
|
88
|
+
if prev_args.owner != self
|
89
|
+
it.own_arguments.delete(arg.graphql_name)
|
90
|
+
end
|
91
|
+
when Array
|
92
|
+
prev_args.reject! { |a| a.owner != self }
|
93
|
+
if prev_args.empty?
|
94
|
+
it.own_arguments.delete(arg.graphql_name)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
it.add_argument(arg)
|
99
|
+
arg
|
100
|
+
end
|
101
|
+
|
102
|
+
# The base class for generated input object types
|
103
|
+
# @param new_class [Class] The base class to use for generating input object definitions
|
104
|
+
# @return [Class] The base class for this mutation's generated input object (default is {GraphQL::Schema::InputObject})
|
105
|
+
def input_object_class(new_class = nil)
|
106
|
+
if new_class
|
107
|
+
@input_object_class = new_class
|
108
|
+
end
|
109
|
+
@input_object_class || (superclass.respond_to?(:input_object_class) ? superclass.input_object_class : GraphQL::Schema::InputObject)
|
110
|
+
end
|
111
|
+
|
112
|
+
# @param new_input_type [Class, nil] If provided, it configures this mutation to accept `new_input_type` instead of generating an input type
|
113
|
+
# @return [Class] The generated {Schema::InputObject} class for this mutation's `input`
|
114
|
+
def input_type(new_input_type = nil)
|
115
|
+
if new_input_type
|
116
|
+
@input_type = new_input_type
|
117
|
+
end
|
118
|
+
@input_type ||= generate_input_type
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
# Generate the input type for the `input:` argument
|
124
|
+
# To customize how input objects are generated, override this method
|
125
|
+
# @return [Class] a subclass of {.input_object_class}
|
126
|
+
def generate_input_type
|
127
|
+
mutation_args = all_argument_definitions
|
128
|
+
mutation_class = self
|
129
|
+
Class.new(input_object_class) do
|
130
|
+
class << self
|
131
|
+
def default_graphql_name
|
132
|
+
"#{self.mutation.graphql_name}Input"
|
133
|
+
end
|
134
|
+
|
135
|
+
def description(new_desc = nil)
|
136
|
+
super || "Autogenerated input type of #{self.mutation.graphql_name}"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
mutation(mutation_class)
|
140
|
+
# these might be inherited:
|
141
|
+
mutation_args.each do |arg|
|
142
|
+
add_argument(arg)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
private
|
149
|
+
|
150
|
+
def authorize_arguments(args, values)
|
151
|
+
# remove the `input` wrapper to match values
|
152
|
+
input_type = args.find { |a| a.graphql_name == "input" }.type.unwrap
|
153
|
+
input_args = context.types.arguments(input_type)
|
154
|
+
super(input_args, values)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -23,7 +23,8 @@ module GraphQL
|
|
23
23
|
@ruby_style_hash = ruby_kwargs
|
24
24
|
@arguments = arguments
|
25
25
|
# Apply prepares, not great to have it duplicated here.
|
26
|
-
self.class.arguments(context).each_value
|
26
|
+
arg_defns = context ? context.types.arguments(self.class) : self.class.arguments(context).each_value
|
27
|
+
arg_defns.each do |arg_defn|
|
27
28
|
ruby_kwargs_key = arg_defn.keyword
|
28
29
|
if @ruby_style_hash.key?(ruby_kwargs_key)
|
29
30
|
# Weirdly, procs are applied during coercion, but not methods.
|
@@ -58,7 +59,7 @@ module GraphQL
|
|
58
59
|
def self.authorized?(obj, value, ctx)
|
59
60
|
# Authorize each argument (but this doesn't apply if `prepare` is implemented):
|
60
61
|
if value.respond_to?(:key?)
|
61
|
-
arguments(
|
62
|
+
ctx.types.arguments(self).each do |input_obj_arg|
|
62
63
|
if value.key?(input_obj_arg.keyword) &&
|
63
64
|
!input_obj_arg.authorized?(obj, value[input_obj_arg.keyword], ctx)
|
64
65
|
return false
|
@@ -69,6 +70,19 @@ module GraphQL
|
|
69
70
|
true
|
70
71
|
end
|
71
72
|
|
73
|
+
def self.one_of
|
74
|
+
if !one_of?
|
75
|
+
if all_argument_definitions.any? { |arg| arg.type.non_null? }
|
76
|
+
raise ArgumentError, "`one_of` may not be used with required arguments -- add `required: false` to argument definitions to use `one_of`"
|
77
|
+
end
|
78
|
+
directive(GraphQL::Schema::Directive::OneOf)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.one_of?
|
83
|
+
false # Re-defined when `OneOf` is added
|
84
|
+
end
|
85
|
+
|
72
86
|
def unwrap_value(value)
|
73
87
|
case value
|
74
88
|
when Array
|
@@ -109,12 +123,21 @@ module GraphQL
|
|
109
123
|
class << self
|
110
124
|
def argument(*args, **kwargs, &block)
|
111
125
|
argument_defn = super(*args, **kwargs, &block)
|
126
|
+
if one_of?
|
127
|
+
if argument_defn.type.non_null?
|
128
|
+
raise ArgumentError, "Argument '#{argument_defn.path}' must be nullable because it is part of a OneOf type, add `required: false`."
|
129
|
+
end
|
130
|
+
if argument_defn.default_value?
|
131
|
+
raise ArgumentError, "Argument '#{argument_defn.path}' cannot have a default value because it is part of a OneOf type, remove `default_value: ...`."
|
132
|
+
end
|
133
|
+
end
|
112
134
|
# Add a method access
|
113
135
|
method_name = argument_defn.keyword
|
114
136
|
class_eval <<-RUBY, __FILE__, __LINE__
|
115
137
|
def #{method_name}
|
116
138
|
self[#{method_name.inspect}]
|
117
139
|
end
|
140
|
+
alias_method :#{method_name}, :#{method_name}
|
118
141
|
RUBY
|
119
142
|
argument_defn
|
120
143
|
end
|
@@ -124,10 +147,10 @@ module GraphQL
|
|
124
147
|
end
|
125
148
|
|
126
149
|
# @api private
|
127
|
-
INVALID_OBJECT_MESSAGE = "Expected %{object} to be a key-value object
|
150
|
+
INVALID_OBJECT_MESSAGE = "Expected %{object} to be a key-value object."
|
128
151
|
|
129
152
|
def validate_non_null_input(input, ctx, max_errors: nil)
|
130
|
-
|
153
|
+
types = ctx.types
|
131
154
|
|
132
155
|
if input.is_a?(Array)
|
133
156
|
return GraphQL::Query::InputValidationResult.from_problem(INVALID_OBJECT_MESSAGE % { object: JSON.generate(input, quirks_mode: true) })
|
@@ -139,9 +162,9 @@ module GraphQL
|
|
139
162
|
end
|
140
163
|
|
141
164
|
# Inject missing required arguments
|
142
|
-
missing_required_inputs =
|
143
|
-
if !input.key?(
|
144
|
-
m[
|
165
|
+
missing_required_inputs = ctx.types.arguments(self).reduce({}) do |m, (argument)|
|
166
|
+
if !input.key?(argument.graphql_name) && argument.type.non_null? && types.argument(self, argument.graphql_name)
|
167
|
+
m[argument.graphql_name] = nil
|
145
168
|
end
|
146
169
|
|
147
170
|
m
|
@@ -150,7 +173,7 @@ module GraphQL
|
|
150
173
|
result = nil
|
151
174
|
[input, missing_required_inputs].each do |args_to_validate|
|
152
175
|
args_to_validate.each do |argument_name, value|
|
153
|
-
argument =
|
176
|
+
argument = types.argument(self, argument_name)
|
154
177
|
# Items in the input that are unexpected
|
155
178
|
if argument.nil?
|
156
179
|
result ||= Query::InputValidationResult.new
|
@@ -166,6 +189,20 @@ module GraphQL
|
|
166
189
|
end
|
167
190
|
end
|
168
191
|
|
192
|
+
if one_of?
|
193
|
+
if input.size == 1
|
194
|
+
input.each do |name, value|
|
195
|
+
if value.nil?
|
196
|
+
result ||= Query::InputValidationResult.new
|
197
|
+
result.add_problem("'#{graphql_name}' requires exactly one argument, but '#{name}' was `null`.")
|
198
|
+
end
|
199
|
+
end
|
200
|
+
else
|
201
|
+
result ||= Query::InputValidationResult.new
|
202
|
+
result.add_problem("'#{graphql_name}' requires exactly one argument, but #{input.size} were provided.")
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
169
206
|
result
|
170
207
|
end
|
171
208
|
|
@@ -176,12 +213,11 @@ module GraphQL
|
|
176
213
|
|
177
214
|
arguments = coerce_arguments(nil, value, ctx)
|
178
215
|
|
179
|
-
ctx.
|
216
|
+
ctx.query.after_lazy(arguments) do |resolved_arguments|
|
180
217
|
if resolved_arguments.is_a?(GraphQL::Error)
|
181
218
|
raise resolved_arguments
|
182
219
|
else
|
183
|
-
|
184
|
-
input_obj_instance.prepare
|
220
|
+
self.new(resolved_arguments, ruby_kwargs: resolved_arguments.keyword_arguments, context: ctx, defaults_used: nil)
|
185
221
|
end
|
186
222
|
end
|
187
223
|
end
|
@@ -20,6 +20,15 @@ module GraphQL
|
|
20
20
|
# - Added as class methods to this interface
|
21
21
|
# - Added as class methods to all child interfaces
|
22
22
|
def definition_methods(&block)
|
23
|
+
# Use an instance variable to tell whether it's been included previously or not;
|
24
|
+
# You can't use constant detection because constants are brought into scope
|
25
|
+
# by `include`, which has already happened at this point.
|
26
|
+
if !defined?(@_definition_methods)
|
27
|
+
defn_methods_module = Module.new
|
28
|
+
@_definition_methods = defn_methods_module
|
29
|
+
const_set(:DefinitionMethods, defn_methods_module)
|
30
|
+
extend(self::DefinitionMethods)
|
31
|
+
end
|
23
32
|
self::DefinitionMethods.module_eval(&block)
|
24
33
|
end
|
25
34
|
|
@@ -28,16 +37,6 @@ module GraphQL
|
|
28
37
|
true
|
29
38
|
end
|
30
39
|
|
31
|
-
# The interface is accessible if any of its possible types are accessible
|
32
|
-
def accessible?(context)
|
33
|
-
context.schema.possible_types(self, context).each do |type|
|
34
|
-
if context.schema.accessible?(type, context)
|
35
|
-
return true
|
36
|
-
end
|
37
|
-
end
|
38
|
-
false
|
39
|
-
end
|
40
|
-
|
41
40
|
def type_membership_class(membership_class = nil)
|
42
41
|
if membership_class
|
43
42
|
@type_membership_class = membership_class
|
@@ -57,20 +56,11 @@ module GraphQL
|
|
57
56
|
|
58
57
|
child_class.type_membership_class(self.type_membership_class)
|
59
58
|
child_class.ancestors.reverse_each do |ancestor|
|
60
|
-
if ancestor.const_defined?(:DefinitionMethods)
|
59
|
+
if ancestor.const_defined?(:DefinitionMethods) && ancestor != child_class
|
61
60
|
child_class.extend(ancestor::DefinitionMethods)
|
62
61
|
end
|
63
62
|
end
|
64
63
|
|
65
|
-
# Use an instance variable to tell whether it's been included previously or not;
|
66
|
-
# You can't use constant detection because constants are brought into scope
|
67
|
-
# by `include`, which has already happened at this point.
|
68
|
-
if !child_class.instance_variable_defined?(:@_definition_methods)
|
69
|
-
defn_methods_module = Module.new
|
70
|
-
child_class.instance_variable_set(:@_definition_methods, defn_methods_module)
|
71
|
-
child_class.const_set(:DefinitionMethods, defn_methods_module)
|
72
|
-
child_class.extend(child_class::DefinitionMethods)
|
73
|
-
end
|
74
64
|
child_class.introspection(introspection)
|
75
65
|
child_class.description(description)
|
76
66
|
# If interfaces are mixed into each other, only define this class once
|
@@ -79,7 +69,11 @@ module GraphQL
|
|
79
69
|
end
|
80
70
|
elsif child_class < GraphQL::Schema::Object
|
81
71
|
# This is being included into an object type, make sure it's using `implements(...)`
|
82
|
-
backtrace_line =
|
72
|
+
backtrace_line = caller_locations(0, 10).find do |location|
|
73
|
+
location.base_label == "implements" &&
|
74
|
+
location.path.end_with?("schema/member/has_interfaces.rb")
|
75
|
+
end
|
76
|
+
|
83
77
|
if !backtrace_line
|
84
78
|
raise "Attach interfaces using `implements(#{self})`, not `include(#{self})`"
|
85
79
|
end
|
@@ -25,10 +25,10 @@ module GraphQL
|
|
25
25
|
load_constant(:DirectiveLocationEnum)
|
26
26
|
]
|
27
27
|
@types = {}
|
28
|
-
@possible_types = {}
|
28
|
+
@possible_types = {}.tap(&: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
|
@@ -111,19 +113,7 @@ module GraphQL
|
|
111
113
|
|
112
114
|
def get_fields_from_class(class_sym:)
|
113
115
|
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
|
116
|
+
object_type_defn.fields
|
127
117
|
end
|
128
118
|
|
129
119
|
# This is probably not 100% robust -- but it has to be good enough to avoid modifying the built-in introspection types
|
@@ -155,7 +145,7 @@ module GraphQL
|
|
155
145
|
if obj.is_a?(GraphQL::Schema::Object)
|
156
146
|
obj = obj.object
|
157
147
|
end
|
158
|
-
wrapped_object = @object_class.
|
148
|
+
wrapped_object = @object_class.wrap(obj, query_ctx)
|
159
149
|
@inner_resolve.call(wrapped_object, args, ctx)
|
160
150
|
end
|
161
151
|
end
|
@@ -9,6 +9,8 @@ module GraphQL
|
|
9
9
|
alias :graphql_name :name
|
10
10
|
def initialize(local_name)
|
11
11
|
@name = local_name
|
12
|
+
@to_non_null_type = nil
|
13
|
+
@to_list_type = nil
|
12
14
|
end
|
13
15
|
|
14
16
|
def unwrap
|
@@ -23,10 +25,18 @@ module GraphQL
|
|
23
25
|
@to_list_type ||= GraphQL::Schema::List.new(self)
|
24
26
|
end
|
25
27
|
|
28
|
+
def to_type_signature
|
29
|
+
name
|
30
|
+
end
|
31
|
+
|
26
32
|
def inspect
|
27
33
|
"#<LateBoundType @name=#{name}>"
|
28
34
|
end
|
29
35
|
|
36
|
+
def non_null?
|
37
|
+
false
|
38
|
+
end
|
39
|
+
|
30
40
|
alias :to_s :inspect
|
31
41
|
end
|
32
42
|
end
|
data/lib/graphql/schema/list.rb
CHANGED
@@ -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,7 +186,6 @@ 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
190
|
if field_hash["args"].any?
|
192
191
|
loader.build_arguments(self, field_hash["args"], type_resolver)
|
@@ -22,14 +22,10 @@ module GraphQL
|
|
22
22
|
GraphQL::NameValidator.validate!(new_name)
|
23
23
|
@graphql_name = new_name
|
24
24
|
else
|
25
|
-
|
25
|
+
@graphql_name ||= default_graphql_name
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
def overridden_graphql_name
|
30
|
-
defined?(@graphql_name) ? @graphql_name : nil
|
31
|
-
end
|
32
|
-
|
33
29
|
# Just a convenience method to point out that people should use graphql_name instead
|
34
30
|
def name(new_name = nil)
|
35
31
|
return super() if new_name.nil?
|
@@ -50,7 +46,7 @@ module GraphQL
|
|
50
46
|
elsif defined?(@description)
|
51
47
|
@description
|
52
48
|
else
|
53
|
-
nil
|
49
|
+
@description = nil
|
54
50
|
end
|
55
51
|
end
|
56
52
|
|
@@ -60,8 +56,12 @@ module GraphQL
|
|
60
56
|
def inherited(child_class)
|
61
57
|
child_class.introspection(introspection)
|
62
58
|
child_class.description(description)
|
63
|
-
|
64
|
-
|
59
|
+
child_class.default_graphql_name = nil
|
60
|
+
|
61
|
+
if defined?(@graphql_name) && @graphql_name && (self.name.nil? || graphql_name != default_graphql_name)
|
62
|
+
child_class.graphql_name(graphql_name)
|
63
|
+
else
|
64
|
+
child_class.graphql_name = nil
|
65
65
|
end
|
66
66
|
super
|
67
67
|
end
|
@@ -79,7 +79,7 @@ module GraphQL
|
|
79
79
|
end
|
80
80
|
|
81
81
|
def introspection?
|
82
|
-
introspection
|
82
|
+
!!@introspection
|
83
83
|
end
|
84
84
|
|
85
85
|
# The mutation this type was derived from, if it was derived from a mutation
|
@@ -102,8 +102,8 @@ module GraphQL
|
|
102
102
|
def default_graphql_name
|
103
103
|
@default_graphql_name ||= begin
|
104
104
|
raise GraphQL::RequiredImplementationMissingError, 'Anonymous class should declare a `graphql_name`' if name.nil?
|
105
|
-
|
106
|
-
|
105
|
+
g_name = -name.split("::").last
|
106
|
+
g_name.end_with?("Type") ? g_name.sub(/Type\Z/, "") : g_name
|
107
107
|
end
|
108
108
|
end
|
109
109
|
|
@@ -111,13 +111,17 @@ module GraphQL
|
|
111
111
|
true
|
112
112
|
end
|
113
113
|
|
114
|
-
def
|
114
|
+
def authorized?(object, context)
|
115
115
|
true
|
116
116
|
end
|
117
117
|
|
118
|
-
def
|
119
|
-
|
118
|
+
def default_relay
|
119
|
+
false
|
120
120
|
end
|
121
|
+
|
122
|
+
protected
|
123
|
+
|
124
|
+
attr_writer :default_graphql_name, :graphql_name
|
121
125
|
end
|
122
126
|
end
|
123
127
|
end
|
@@ -109,7 +109,14 @@ module GraphQL
|
|
109
109
|
to_type_name(something.name)
|
110
110
|
end
|
111
111
|
when String
|
112
|
-
something.
|
112
|
+
if something.include?("]") ||
|
113
|
+
something.include?("[") ||
|
114
|
+
something.include?("!") ||
|
115
|
+
something.include?("::")
|
116
|
+
something.gsub(/\]\[\!/, "").split("::").last
|
117
|
+
else
|
118
|
+
something
|
119
|
+
end
|
113
120
|
when GraphQL::Schema::NonNull, GraphQL::Schema::List
|
114
121
|
to_type_name(something.unwrap)
|
115
122
|
else
|
@@ -120,9 +127,10 @@ module GraphQL
|
|
120
127
|
def camelize(string)
|
121
128
|
return string if string == '_'
|
122
129
|
return string unless string.include?("_")
|
123
|
-
camelized = string.split('_').
|
130
|
+
camelized = string.split('_').each(&:capitalize!).join
|
124
131
|
camelized[0] = camelized[0].downcase
|
125
|
-
if
|
132
|
+
if string.start_with?("_")
|
133
|
+
match_data = string.match(/\A(_+)/)
|
126
134
|
camelized = "#{match_data[0]}#{camelized}"
|
127
135
|
end
|
128
136
|
camelized
|