graphql 1.8.0.pre2 → 1.8.0.pre3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/graphql.rb +1 -1
- data/lib/graphql/deprecated_dsl.rb +2 -0
- data/lib/graphql/enum_type.rb +1 -1
- data/lib/graphql/field.rb +10 -1
- data/lib/graphql/input_object_type.rb +3 -1
- data/lib/graphql/introspection.rb +3 -10
- data/lib/graphql/introspection/base_object.rb +15 -0
- data/lib/graphql/introspection/directive_location_enum.rb +11 -7
- data/lib/graphql/introspection/directive_type.rb +23 -16
- data/lib/graphql/introspection/dynamic_fields.rb +11 -0
- data/lib/graphql/introspection/entry_points.rb +29 -0
- data/lib/graphql/introspection/enum_value_type.rb +16 -11
- data/lib/graphql/introspection/field_type.rb +21 -12
- data/lib/graphql/introspection/input_value_type.rb +26 -23
- data/lib/graphql/introspection/schema_field.rb +7 -2
- data/lib/graphql/introspection/schema_type.rb +36 -22
- data/lib/graphql/introspection/type_by_name_field.rb +10 -2
- data/lib/graphql/introspection/type_kind_enum.rb +10 -6
- data/lib/graphql/introspection/type_type.rb +85 -23
- data/lib/graphql/introspection/typename_field.rb +1 -0
- data/lib/graphql/language.rb +1 -0
- data/lib/graphql/language/document_from_schema_definition.rb +129 -37
- data/lib/graphql/language/generation.rb +3 -182
- data/lib/graphql/language/nodes.rb +12 -2
- data/lib/graphql/language/parser.rb +63 -55
- data/lib/graphql/language/parser.y +2 -1
- data/lib/graphql/language/printer.rb +351 -0
- data/lib/graphql/object_type.rb +1 -1
- data/lib/graphql/query.rb +1 -1
- data/lib/graphql/query/arguments.rb +24 -8
- data/lib/graphql/query/context.rb +3 -0
- data/lib/graphql/query/literal_input.rb +4 -1
- data/lib/graphql/railtie.rb +28 -6
- data/lib/graphql/schema.rb +42 -7
- data/lib/graphql/schema/enum.rb +1 -0
- data/lib/graphql/schema/field.rb +26 -5
- data/lib/graphql/schema/field/dynamic_resolve.rb +18 -9
- data/lib/graphql/schema/input_object.rb +2 -2
- data/lib/graphql/schema/introspection_system.rb +93 -0
- data/lib/graphql/schema/late_bound_type.rb +32 -0
- data/lib/graphql/schema/member.rb +21 -1
- data/lib/graphql/schema/member/build_type.rb +8 -6
- data/lib/graphql/schema/member/has_fields.rb +1 -1
- data/lib/graphql/schema/member/instrumentation.rb +3 -1
- data/lib/graphql/schema/member/list_type_proxy.rb +4 -0
- data/lib/graphql/schema/member/non_null_type_proxy.rb +4 -0
- data/lib/graphql/schema/object.rb +2 -1
- data/lib/graphql/schema/printer.rb +33 -266
- data/lib/graphql/schema/traversal.rb +74 -6
- data/lib/graphql/schema/validation.rb +3 -2
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +6 -6
- data/lib/graphql/tracing/scout_tracing.rb +2 -2
- data/lib/graphql/upgrader/member.rb +463 -63
- data/lib/graphql/version.rb +1 -1
- data/spec/fixtures/upgrader/blame_range.original.rb +43 -0
- data/spec/fixtures/upgrader/blame_range.transformed.rb +31 -0
- data/spec/fixtures/upgrader/subscribable.original.rb +51 -0
- data/spec/fixtures/upgrader/subscribable.transformed.rb +46 -0
- data/spec/fixtures/upgrader/type_x.original.rb +35 -0
- data/spec/fixtures/upgrader/type_x.transformed.rb +35 -0
- data/spec/graphql/language/document_from_schema_definition_spec.rb +729 -296
- data/spec/graphql/language/generation_spec.rb +21 -186
- data/spec/graphql/language/nodes_spec.rb +21 -0
- data/spec/graphql/language/printer_spec.rb +203 -0
- data/spec/graphql/query/arguments_spec.rb +14 -4
- data/spec/graphql/query/context_spec.rb +17 -0
- data/spec/graphql/schema/build_from_definition_spec.rb +13 -4
- data/spec/graphql/schema/field_spec.rb +14 -0
- data/spec/graphql/schema/introspection_system_spec.rb +39 -0
- data/spec/graphql/schema/object_spec.rb +12 -1
- data/spec/graphql/schema/printer_spec.rb +14 -14
- data/spec/graphql/tracing/platform_tracing_spec.rb +2 -2
- data/spec/graphql/upgrader/member_spec.rb +274 -62
- data/spec/support/jazz.rb +75 -3
- metadata +38 -9
- data/lib/graphql/introspection/arguments_field.rb +0 -7
- data/lib/graphql/introspection/enum_values_field.rb +0 -18
- data/lib/graphql/introspection/fields_field.rb +0 -13
- data/lib/graphql/introspection/input_fields_field.rb +0 -12
- data/lib/graphql/introspection/interfaces_field.rb +0 -11
- data/lib/graphql/introspection/of_type_field.rb +0 -6
- data/lib/graphql/introspection/possible_types_field.rb +0 -11
data/lib/graphql/object_type.rb
CHANGED
@@ -32,7 +32,7 @@ module GraphQL
|
|
32
32
|
# @return [Hash<String => GraphQL::Field>] Map String fieldnames to their {GraphQL::Field} implementations
|
33
33
|
|
34
34
|
# @!attribute mutation
|
35
|
-
# @return [GraphQL::Relay::Mutation, nil] The mutation this
|
35
|
+
# @return [GraphQL::Relay::Mutation, nil] The mutation this object type was derived from, if it is an auto-generated payload type.
|
36
36
|
|
37
37
|
def initialize
|
38
38
|
super
|
data/lib/graphql/query.rb
CHANGED
@@ -79,7 +79,7 @@ module GraphQL
|
|
79
79
|
def initialize(schema, query_string = nil, query: nil, document: nil, context: nil, variables: {}, validate: true, subscription_topic: nil, operation_name: nil, root_value: nil, max_depth: nil, max_complexity: nil, except: nil, only: nil)
|
80
80
|
@schema = schema
|
81
81
|
@filter = schema.default_filter.merge(except: except, only: only)
|
82
|
-
@context =
|
82
|
+
@context = schema.context_class.new(query: self, object: root_value, values: context)
|
83
83
|
@subscription_topic = subscription_topic
|
84
84
|
@root_value = root_value
|
85
85
|
@fragments = nil
|
@@ -35,13 +35,14 @@ module GraphQL
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
def initialize(values, context:)
|
38
|
+
def initialize(values, context:, defaults_used:)
|
39
39
|
@argument_values = values.inject({}) do |memo, (inner_key, inner_value)|
|
40
|
-
|
41
|
-
|
40
|
+
arg_name = inner_key.to_s
|
41
|
+
arg_defn = self.class.argument_definitions[arg_name]
|
42
|
+
arg_default_used = defaults_used.include?(arg_name)
|
42
43
|
arg_value = wrap_value(inner_value, arg_defn.type, context)
|
43
44
|
string_key = arg_defn.expose_as
|
44
|
-
memo[string_key] = ArgumentValue.new(string_key, arg_value, arg_defn)
|
45
|
+
memo[string_key] = ArgumentValue.new(string_key, arg_value, arg_defn, arg_default_used)
|
45
46
|
memo
|
46
47
|
end
|
47
48
|
end
|
@@ -60,6 +61,13 @@ module GraphQL
|
|
60
61
|
@argument_values.key?(key_s)
|
61
62
|
end
|
62
63
|
|
64
|
+
# @param key [String, Symbol] name of value to access
|
65
|
+
# @return [Boolean] true if the argument default was passed as the argument value to the resolver
|
66
|
+
def default_used?(key)
|
67
|
+
key_s = key.is_a?(String) ? key : key.to_s
|
68
|
+
@argument_values.fetch(key_s, NULL_ARGUMENT_VALUE).default_used?
|
69
|
+
end
|
70
|
+
|
63
71
|
# Get the hash of all values, with stringified keys
|
64
72
|
# @return [Hash] the stringified hash
|
65
73
|
def to_h
|
@@ -92,20 +100,28 @@ module GraphQL
|
|
92
100
|
self.argument_definitions = []
|
93
101
|
end
|
94
102
|
|
95
|
-
NO_ARGS = NoArguments.new({}, context: nil)
|
103
|
+
NO_ARGS = NoArguments.new({}, context: nil, defaults_used: Set.new)
|
96
104
|
|
97
105
|
private
|
98
106
|
|
99
107
|
class ArgumentValue
|
100
108
|
attr_reader :key, :value, :definition
|
101
|
-
|
109
|
+
attr_writer :default_used
|
110
|
+
|
111
|
+
def initialize(key, value, definition, default_used)
|
102
112
|
@key = key
|
103
113
|
@value = value
|
104
114
|
@definition = definition
|
115
|
+
@default_used = default_used
|
116
|
+
end
|
117
|
+
|
118
|
+
# @return [Boolean] true if the argument default was passed as the argument value to the resolver
|
119
|
+
def default_used?
|
120
|
+
@default_used
|
105
121
|
end
|
106
122
|
end
|
107
123
|
|
108
|
-
NULL_ARGUMENT_VALUE = ArgumentValue.new(nil, nil, nil)
|
124
|
+
NULL_ARGUMENT_VALUE = ArgumentValue.new(nil, nil, nil, nil)
|
109
125
|
|
110
126
|
def wrap_value(value, arg_defn_type, context)
|
111
127
|
if value.nil?
|
@@ -118,7 +134,7 @@ module GraphQL
|
|
118
134
|
wrap_value(value, arg_defn_type.of_type, context)
|
119
135
|
when GraphQL::InputObjectType
|
120
136
|
if value.is_a?(Hash)
|
121
|
-
arg_defn_type.arguments_class.new(value, context: context)
|
137
|
+
arg_defn_type.arguments_class.new(value, context: context, defaults_used: Set.new)
|
122
138
|
else
|
123
139
|
value
|
124
140
|
end
|
@@ -49,6 +49,8 @@ module GraphQL
|
|
49
49
|
def self.from_arguments(ast_arguments, argument_owner, variables)
|
50
50
|
context = variables ? variables.context : nil
|
51
51
|
values_hash = {}
|
52
|
+
defaults_used = Set.new
|
53
|
+
|
52
54
|
indexed_arguments = case ast_arguments
|
53
55
|
when Hash
|
54
56
|
ast_arguments
|
@@ -93,6 +95,7 @@ module GraphQL
|
|
93
95
|
# then add the default value.
|
94
96
|
if arg_defn.default_value? && !values_hash.key?(arg_name)
|
95
97
|
value = arg_defn.default_value
|
98
|
+
defaults_used << arg_name
|
96
99
|
# `context` isn't present when pre-calculating defaults
|
97
100
|
if context
|
98
101
|
value = arg_defn.prepare(value, context)
|
@@ -105,7 +108,7 @@ module GraphQL
|
|
105
108
|
end
|
106
109
|
end
|
107
110
|
|
108
|
-
argument_owner.arguments_class.new(values_hash, context: context)
|
111
|
+
argument_owner.arguments_class.new(values_hash, context: context, defaults_used: defaults_used)
|
109
112
|
end
|
110
113
|
end
|
111
114
|
end
|
data/lib/graphql/railtie.rb
CHANGED
@@ -19,17 +19,40 @@ module GraphQL
|
|
19
19
|
Rake::Task["graphql:upgrade:member"].execute(Struct.new(:member_file).new(file))
|
20
20
|
end
|
21
21
|
end
|
22
|
+
|
23
|
+
puts "Upgrade complete! Note that this is a best-effort approach, and may very well contain some bugs."
|
24
|
+
puts "Don't forget to create the base objects. For example, you could run:"
|
25
|
+
puts "\tbin/rake graphql:upgrade:create_base_objects[app/graphql]"
|
22
26
|
end
|
23
27
|
|
24
28
|
namespace :upgrade do
|
25
29
|
task :create_base_objects, [:base_dir] do |t, args|
|
26
|
-
base_dir = args
|
30
|
+
unless (base_dir = args[:base_dir])
|
31
|
+
fail 'You have to give me a directory where your GraphQL types live. ' \
|
32
|
+
'For example: `bin/rake graphql:upgrade:create_base_objects[app/graphql]`'
|
33
|
+
end
|
34
|
+
|
35
|
+
destination_file = File.join(base_dir, "types", "base_scalar.rb")
|
36
|
+
unless File.exists?(destination_file)
|
37
|
+
FileUtils.mkdir_p(File.dirname(destination_file))
|
38
|
+
File.open(destination_file, 'w') do |f|
|
39
|
+
f.write "class Types::BaseScalar < GraphQL::Schema::Scalar\nend"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
destination_file = File.join(base_dir, "types", "base_input_object.rb")
|
44
|
+
unless File.exists?(destination_file)
|
45
|
+
FileUtils.mkdir_p(File.dirname(destination_file))
|
46
|
+
File.open(destination_file, 'w') do |f|
|
47
|
+
f.write "class Types::BaseInputObject < GraphQL::Schema::InputObject\nend"
|
48
|
+
end
|
49
|
+
end
|
27
50
|
|
28
51
|
destination_file = File.join(base_dir, "types", "base_enum.rb")
|
29
52
|
unless File.exists?(destination_file)
|
30
53
|
FileUtils.mkdir_p(File.dirname(destination_file))
|
31
54
|
File.open(destination_file, 'w') do |f|
|
32
|
-
f.write "class Types::BaseEnum < GraphQL::Schema::Enum
|
55
|
+
f.write "class Types::BaseEnum < GraphQL::Schema::Enum\nend"
|
33
56
|
end
|
34
57
|
end
|
35
58
|
|
@@ -37,7 +60,7 @@ module GraphQL
|
|
37
60
|
unless File.exists?(destination_file)
|
38
61
|
FileUtils.mkdir_p(File.dirname(destination_file))
|
39
62
|
File.open(destination_file, 'w') do |f|
|
40
|
-
f.write "class Types::BaseUnion < GraphQL::Schema::Union
|
63
|
+
f.write "class Types::BaseUnion < GraphQL::Schema::Union\nend"
|
41
64
|
end
|
42
65
|
end
|
43
66
|
|
@@ -45,14 +68,14 @@ module GraphQL
|
|
45
68
|
unless File.exists?(destination_file)
|
46
69
|
FileUtils.mkdir_p(File.dirname(destination_file))
|
47
70
|
File.open(destination_file, 'w') do |f|
|
48
|
-
f.write "class Types::BaseInterface < GraphQL::Schema::Interface
|
71
|
+
f.write "class Types::BaseInterface < GraphQL::Schema::Interface\nend"
|
49
72
|
end
|
50
73
|
end
|
51
74
|
|
52
75
|
destination_file = File.join(base_dir, "types", "base_object.rb")
|
53
76
|
unless File.exists?(destination_file)
|
54
77
|
File.open(destination_file, 'w') do |f|
|
55
|
-
f.write "class Types::BaseObject < GraphQL::Schema::Object
|
78
|
+
f.write "class Types::BaseObject < GraphQL::Schema::Object\nend"
|
56
79
|
end
|
57
80
|
end
|
58
81
|
end
|
@@ -80,4 +103,3 @@ module GraphQL
|
|
80
103
|
end
|
81
104
|
end
|
82
105
|
end
|
83
|
-
|
data/lib/graphql/schema.rb
CHANGED
@@ -4,6 +4,8 @@ require "graphql/schema/catchall_middleware"
|
|
4
4
|
require "graphql/schema/default_parse_error"
|
5
5
|
require "graphql/schema/default_type_error"
|
6
6
|
require "graphql/schema/invalid_type_error"
|
7
|
+
require "graphql/schema/introspection_system"
|
8
|
+
require "graphql/schema/late_bound_type"
|
7
9
|
require "graphql/schema/middleware_chain"
|
8
10
|
require "graphql/schema/null_mask"
|
9
11
|
require "graphql/schema/possible_types"
|
@@ -91,7 +93,7 @@ module GraphQL
|
|
91
93
|
:orphan_types, :directives,
|
92
94
|
:query_analyzers, :multiplex_analyzers, :instrumenters, :lazy_methods,
|
93
95
|
:cursor_encoder,
|
94
|
-
:raise_definition_error
|
96
|
+
:raise_definition_error, :introspection_namespace
|
95
97
|
|
96
98
|
# Single, long-lived instance of the provided subscriptions class, if there is one.
|
97
99
|
# @return [GraphQL::Subscriptions]
|
@@ -104,6 +106,10 @@ module GraphQL
|
|
104
106
|
# @see {Query.new} for query-specific filters with `except:`
|
105
107
|
attr_accessor :default_mask
|
106
108
|
|
109
|
+
# @see {GraphQL::Query::Context} The parent class of these classes
|
110
|
+
# @return [Class] Instantiated for each query
|
111
|
+
attr_accessor :context_class
|
112
|
+
|
107
113
|
class << self
|
108
114
|
attr_accessor :default_execution_strategy
|
109
115
|
end
|
@@ -148,6 +154,9 @@ module GraphQL
|
|
148
154
|
@subscription_execution_strategy = self.class.default_execution_strategy
|
149
155
|
@default_mask = GraphQL::Schema::NullMask
|
150
156
|
@rebuilding_artifacts = false
|
157
|
+
@context_class = GraphQL::Query::Context
|
158
|
+
@introspection_namespace = nil
|
159
|
+
@introspection_system = nil
|
151
160
|
end
|
152
161
|
|
153
162
|
def initialize_copy(other)
|
@@ -175,6 +184,7 @@ module GraphQL
|
|
175
184
|
# This will be rebuilt when it's requested
|
176
185
|
# or during a later `define` call
|
177
186
|
@types = nil
|
187
|
+
@introspection_system = nil
|
178
188
|
end
|
179
189
|
|
180
190
|
def rescue_from(*args, &block)
|
@@ -250,6 +260,14 @@ module GraphQL
|
|
250
260
|
end
|
251
261
|
end
|
252
262
|
|
263
|
+
# @api private
|
264
|
+
def introspection_system
|
265
|
+
@introspection_system ||= begin
|
266
|
+
rebuild_artifacts
|
267
|
+
@introspection_system
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
253
271
|
# Returns a list of Arguments and Fields referencing a certain type
|
254
272
|
# @param type_name [String]
|
255
273
|
# @return [Hash]
|
@@ -331,12 +349,10 @@ module GraphQL
|
|
331
349
|
defined_field = @instrumented_field_map[parent_type_name][field_name]
|
332
350
|
if defined_field
|
333
351
|
defined_field
|
334
|
-
elsif
|
335
|
-
|
336
|
-
elsif
|
337
|
-
|
338
|
-
elsif field_name == "__type" && parent_type == query
|
339
|
-
GraphQL::Introspection::TypeByNameField
|
352
|
+
elsif parent_type == query && (entry_point_field = introspection_system.entry_point(name: field_name))
|
353
|
+
entry_point_field
|
354
|
+
elsif (dynamic_field = introspection_system.dynamic_field(name: field_name))
|
355
|
+
dynamic_field
|
340
356
|
else
|
341
357
|
nil
|
342
358
|
end
|
@@ -632,9 +648,11 @@ module GraphQL
|
|
632
648
|
directives(DIRECTIVES)
|
633
649
|
end
|
634
650
|
schema_defn.directives = directives
|
651
|
+
schema_defn.introspection_namespace = introspection
|
635
652
|
schema_defn.resolve_type = method(:resolve_type)
|
636
653
|
schema_defn.object_from_id = method(:object_from_id)
|
637
654
|
schema_defn.id_from_object = method(:id_from_object)
|
655
|
+
schema_defn.context_class = context_class
|
638
656
|
instrumenters.each do |step, insts|
|
639
657
|
insts.each do |inst|
|
640
658
|
schema_defn.instrumenters[step] << inst
|
@@ -686,6 +704,14 @@ module GraphQL
|
|
686
704
|
end
|
687
705
|
end
|
688
706
|
|
707
|
+
def introspection(new_introspection_namespace = nil)
|
708
|
+
if new_introspection_namespace
|
709
|
+
@introspection = new_introspection_namespace
|
710
|
+
else
|
711
|
+
@introspection
|
712
|
+
end
|
713
|
+
end
|
714
|
+
|
689
715
|
def default_max_page_size(new_default_max_page_size = nil)
|
690
716
|
if new_default_max_page_size
|
691
717
|
@default_max_page_size = new_default_max_page_size
|
@@ -718,6 +744,14 @@ module GraphQL
|
|
718
744
|
end
|
719
745
|
end
|
720
746
|
|
747
|
+
def context_class(new_context_class = nil)
|
748
|
+
if new_context_class
|
749
|
+
@context_class = new_context_class
|
750
|
+
else
|
751
|
+
@context_class || GraphQL::Query::Context
|
752
|
+
end
|
753
|
+
end
|
754
|
+
|
721
755
|
def resolve_type(type, obj, ctx)
|
722
756
|
raise NotImplementedError, "#{self.name}.resolve_type(type, obj, ctx) must be implemented to use Union types or Interface types (tried to resolve: #{type.name})"
|
723
757
|
end
|
@@ -805,6 +839,7 @@ module GraphQL
|
|
805
839
|
raise CyclicalDefinitionError, "Part of the schema build process re-triggered the schema build process, causing an infinite loop. Avoid using Schema#types, Schema#possible_types, and Schema#get_field during schema build."
|
806
840
|
else
|
807
841
|
@rebuilding_artifacts = true
|
842
|
+
@introspection_system = Schema::IntrospectionSystem.new(self)
|
808
843
|
traversal = Traversal.new(self)
|
809
844
|
@types = traversal.type_map
|
810
845
|
@root_types = [query, mutation, subscription]
|
data/lib/graphql/schema/enum.rb
CHANGED
@@ -54,6 +54,7 @@ module GraphQL
|
|
54
54
|
enum_type = GraphQL::EnumType.new
|
55
55
|
enum_type.name = graphql_name
|
56
56
|
enum_type.description = description
|
57
|
+
enum_type.introspection = introspection
|
57
58
|
values.each do |val|
|
58
59
|
enum_value = GraphQL::EnumType::EnumValue.new
|
59
60
|
enum_value.name = val.name
|
data/lib/graphql/schema/field.rb
CHANGED
@@ -13,7 +13,7 @@ module GraphQL
|
|
13
13
|
# @return [String]
|
14
14
|
attr_reader :description
|
15
15
|
|
16
|
-
def initialize(name, return_type_expr = nil, desc = nil, null: nil, field: nil, function: nil, deprecation_reason: nil, method: nil, connection: nil, max_page_size: nil, resolve: nil, &args_block)
|
16
|
+
def initialize(name, return_type_expr = nil, desc = nil, null: nil, field: nil, function: nil, description: nil, deprecation_reason: nil, method: nil, connection: nil, max_page_size: nil, resolve: nil, introspection: false, extras: [], &args_block)
|
17
17
|
if !(field || function)
|
18
18
|
if return_type_expr.nil?
|
19
19
|
raise ArgumentError, "missing positional argument `type`"
|
@@ -22,8 +22,14 @@ module GraphQL
|
|
22
22
|
raise ArgumentError, "missing keyword argument null:"
|
23
23
|
end
|
24
24
|
end
|
25
|
+
if (field || function || resolve) && extras.any?
|
26
|
+
raise ArgumentError, "keyword `extras:` may only be used with method-based resolve, please remove `field:`, `function:`, or `resolve:`"
|
27
|
+
end
|
25
28
|
@name = name.to_s
|
26
|
-
|
29
|
+
if description && desc
|
30
|
+
raise ArgumentError, "Provide description as a positional argument or `description:` keyword, but not both (#{desc.inspect}, #{description.inspect})"
|
31
|
+
end
|
32
|
+
@description = description || desc
|
27
33
|
@field = field
|
28
34
|
@function = function
|
29
35
|
@resolve = resolve
|
@@ -34,6 +40,8 @@ module GraphQL
|
|
34
40
|
@args_block = args_block
|
35
41
|
@connection = connection
|
36
42
|
@max_page_size = max_page_size
|
43
|
+
@introspection = introspection
|
44
|
+
@extras = extras
|
37
45
|
end
|
38
46
|
|
39
47
|
# @return [GraphQL::Field]
|
@@ -49,7 +57,6 @@ module GraphQL
|
|
49
57
|
end
|
50
58
|
|
51
59
|
field_defn.name = Member::BuildType.camelize(name)
|
52
|
-
|
53
60
|
if @return_type_expr
|
54
61
|
return_type_name = Member::BuildType.to_type_name(@return_type_expr)
|
55
62
|
connection = @connection.nil? ? return_type_name.end_with?("Connection") : @connection
|
@@ -75,11 +82,16 @@ module GraphQL
|
|
75
82
|
prev_resolve = @resolve || field_defn.resolve_proc
|
76
83
|
UnwrappedResolve.new(inner_resolve: prev_resolve)
|
77
84
|
else
|
78
|
-
DynamicResolve.new(
|
85
|
+
DynamicResolve.new(
|
86
|
+
method_name: method_name,
|
87
|
+
connection: connection,
|
88
|
+
extras: @extras
|
89
|
+
)
|
79
90
|
end
|
80
91
|
|
81
92
|
field_defn.connection = connection
|
82
93
|
field_defn.connection_max_page_size = @max_page_size
|
94
|
+
field_defn.introspection = @introspection
|
83
95
|
|
84
96
|
field_proxy = FieldProxy.new(field_defn, argument_class: self.class.argument_class)
|
85
97
|
# apply this first, so it can be overriden below
|
@@ -122,7 +134,16 @@ module GraphQL
|
|
122
134
|
# This is the `argument(...)` DSL for class-based field definitons
|
123
135
|
def argument(*args)
|
124
136
|
arg = @argument_class.new(*args)
|
125
|
-
|
137
|
+
graphql_arg = arg.graphql_definition
|
138
|
+
@field.arguments[graphql_arg.name] = graphql_arg
|
139
|
+
end
|
140
|
+
|
141
|
+
def description(text)
|
142
|
+
if @field.description
|
143
|
+
fail "You're overriding the description of #{@field.name} in the provided block!"
|
144
|
+
else
|
145
|
+
@field.description = text
|
146
|
+
end
|
126
147
|
end
|
127
148
|
end
|
128
149
|
end
|
@@ -4,16 +4,17 @@ module GraphQL
|
|
4
4
|
class Schema
|
5
5
|
class Field
|
6
6
|
class DynamicResolve
|
7
|
-
def initialize(method_name:, connection:)
|
7
|
+
def initialize(method_name:, connection:, extras:)
|
8
8
|
@method_name = method_name
|
9
9
|
@connection = connection
|
10
|
+
@extras = extras
|
10
11
|
end
|
11
12
|
|
12
13
|
def call(obj, args, ctx)
|
13
14
|
if obj.respond_to?(@method_name)
|
14
|
-
public_send_field(obj, @method_name, args)
|
15
|
+
public_send_field(obj, @method_name, args, ctx)
|
15
16
|
elsif obj.object.respond_to?(@method_name)
|
16
|
-
public_send_field(obj.object, @method_name, args)
|
17
|
+
public_send_field(obj.object, @method_name, args, ctx)
|
17
18
|
elsif obj.is_a?(Hash)
|
18
19
|
obj[@method_name]
|
19
20
|
else
|
@@ -31,8 +32,10 @@ ERR
|
|
31
32
|
|
32
33
|
private
|
33
34
|
|
34
|
-
|
35
|
-
|
35
|
+
NO_ARGS = {}.freeze
|
36
|
+
|
37
|
+
def public_send_field(obj, method_name, graphql_args, field_ctx)
|
38
|
+
if graphql_args.any? || @extras.any?
|
36
39
|
# Splat the GraphQL::Arguments to Ruby keyword arguments
|
37
40
|
ruby_kwargs = {}
|
38
41
|
|
@@ -48,11 +51,17 @@ ERR
|
|
48
51
|
ruby_kwargs.delete(:after)
|
49
52
|
end
|
50
53
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
obj.public_send(method_name)
|
54
|
+
@extras.each do |extra_arg|
|
55
|
+
# TODO: provide proper tests for `:ast_node`, `:irep_node`, `:parent`, others?
|
56
|
+
ruby_kwargs[extra_arg] = field_ctx.public_send(extra_arg)
|
55
57
|
end
|
58
|
+
else
|
59
|
+
ruby_kwargs = NO_ARGS
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
if ruby_kwargs.any?
|
64
|
+
obj.public_send(method_name, ruby_kwargs)
|
56
65
|
else
|
57
66
|
obj.public_send(method_name)
|
58
67
|
end
|