1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
# frozen_string_literal: true
module GraphQL
class Schema
module HasSingleInputArgument
def resolve_with_support(**inputs)
if inputs[:input].is_a?(InputObject)
input = inputs[:input].to_kwargs
else
input = inputs[:input]
end
new_extras = field ? field.extras : []
all_extras = self.class.extras + new_extras
# Transfer these from the top-level hash to the
# shortcutted `input:` object
all_extras.each do |ext|
# It's possible that the `extra` was not passed along by this point,
# don't re-add it if it wasn't given here.
if inputs.key?(ext)
input[ext] = inputs[ext]
end
end
if input
# This is handled by Relay::Mutation::Resolve, a bit hacky, but here we are.
input_kwargs = input.to_h
else
# Relay Classic Mutations with no `argument`s
# don't require `input:`
input_kwargs = {}
end
if input_kwargs.any?
super(**input_kwargs)
else
super()
end
end
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def dummy
@dummy ||= begin
d = Class.new(GraphQL::Schema::Resolver)
d.argument_class(self.argument_class)
# TODO make this lazier?
d.argument(:input, input_type, description: "Parameters for #{self.graphql_name}")
d
end
end
def field_arguments(context = GraphQL::Query::NullContext.instance)
dummy.arguments(context)
end
def get_field_argument(name, context = GraphQL::Query::NullContext.instance)
dummy.get_argument(name, context)
end
def own_field_arguments
dummy.own_arguments
end
def any_field_arguments?
dummy.any_arguments?
end
def all_field_argument_definitions
dummy.all_argument_definitions
end
# Also apply this argument to the input type:
def argument(*args, own_argument: false, **kwargs, &block)
it = input_type # make sure any inherited arguments are already added to it
arg = super(*args, **kwargs, &block)
# This definition might be overriding something inherited;
# if it is, remove the inherited definition so it's not confused at runtime as having multiple definitions
prev_args = it.own_arguments[arg.graphql_name]
case prev_args
when GraphQL::Schema::Argument
if prev_args.owner != self
it.own_arguments.delete(arg.graphql_name)
end
when Array
prev_args.reject! { |a| a.owner != self }
if prev_args.empty?
it.own_arguments.delete(arg.graphql_name)
end
end
it.add_argument(arg)
arg
end
# The base class for generated input object types
# @param new_class [Class] The base class to use for generating input object definitions
# @return [Class] The base class for this mutation's generated input object (default is {GraphQL::Schema::InputObject})
def input_object_class(new_class = nil)
if new_class
@input_object_class = new_class
end
@input_object_class || (superclass.respond_to?(:input_object_class) ? superclass.input_object_class : GraphQL::Schema::InputObject)
end
# @param new_input_type [Class, nil] If provided, it configures this mutation to accept `new_input_type` instead of generating an input type
# @return [Class] The generated {Schema::InputObject} class for this mutation's `input`
def input_type(new_input_type = nil)
if new_input_type
@input_type = new_input_type
end
@input_type ||= generate_input_type
end
private
# Generate the input type for the `input:` argument
# To customize how input objects are generated, override this method
# @return [Class] a subclass of {.input_object_class}
def generate_input_type
mutation_args = all_argument_definitions
mutation_class = self
Class.new(input_object_class) do
class << self
def default_graphql_name
"#{self.mutation.graphql_name}Input"
end
def description(new_desc = nil)
super || "Autogenerated input type of #{self.mutation.graphql_name}"
end
end
mutation(mutation_class)
# these might be inherited:
mutation_args.each do |arg|
add_argument(arg)
end
end
end
end
private
def authorize_arguments(args, values)
# remove the `input` wrapper to match values
input_args = args["input"].type.unwrap.arguments(context)
super(input_args, values)
end
end
end
end
|