graphql 1.10.5 → 1.10.6
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_generator.rb +27 -0
- data/lib/generators/graphql/templates/graphql_controller.erb +1 -1
- data/lib/graphql/execution/interpreter.rb +13 -0
- data/lib/graphql/execution/interpreter/arguments_cache.rb +10 -1
- data/lib/graphql/execution/interpreter/runtime.rb +72 -64
- data/lib/graphql/interface_type.rb +5 -0
- data/lib/graphql/language/nodes.rb +4 -4
- data/lib/graphql/object_type.rb +44 -35
- data/lib/graphql/pagination/connection.rb +24 -4
- data/lib/graphql/pagination/relation_connection.rb +19 -11
- data/lib/graphql/query.rb +28 -1
- data/lib/graphql/query/arguments.rb +2 -1
- data/lib/graphql/query/fingerprint.rb +24 -0
- data/lib/graphql/rake_task.rb +9 -9
- data/lib/graphql/schema.rb +90 -92
- data/lib/graphql/schema/field.rb +33 -13
- data/lib/graphql/schema/field/connection_extension.rb +3 -1
- data/lib/graphql/schema/input_object.rb +14 -2
- data/lib/graphql/schema/interface.rb +10 -0
- data/lib/graphql/schema/loader.rb +1 -1
- data/lib/graphql/schema/member/has_arguments.rb +21 -9
- data/lib/graphql/schema/object.rb +53 -17
- data/lib/graphql/schema/possible_types.rb +9 -4
- data/lib/graphql/schema/warden.rb +48 -7
- data/lib/graphql/types/big_int.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- metadata +3 -2
@@ -12,7 +12,7 @@ module GraphQL
|
|
12
12
|
|
13
13
|
def has_previous_page
|
14
14
|
if @has_previous_page.nil?
|
15
|
-
@has_previous_page = if
|
15
|
+
@has_previous_page = if after_offset && after_offset > 0
|
16
16
|
true
|
17
17
|
elsif last
|
18
18
|
# See whether there are any nodes _before_ the current offset.
|
@@ -29,7 +29,7 @@ module GraphQL
|
|
29
29
|
|
30
30
|
def has_next_page
|
31
31
|
if @has_next_page.nil?
|
32
|
-
@has_next_page = if
|
32
|
+
@has_next_page = if before_offset && before_offset > 0
|
33
33
|
true
|
34
34
|
elsif first
|
35
35
|
relation_count(set_limit(sliced_nodes, first + 1)) == first + 1
|
@@ -105,33 +105,41 @@ module GraphQL
|
|
105
105
|
def sliced_nodes
|
106
106
|
@sliced_nodes ||= begin
|
107
107
|
paginated_nodes = items
|
108
|
-
@after_offset = after && offset_from_cursor(after)
|
109
|
-
@before_offset = before && offset_from_cursor(before)
|
110
108
|
|
111
|
-
if
|
109
|
+
if after_offset
|
112
110
|
previous_offset = relation_offset(items) || 0
|
113
|
-
paginated_nodes = set_offset(paginated_nodes, previous_offset +
|
111
|
+
paginated_nodes = set_offset(paginated_nodes, previous_offset + after_offset)
|
114
112
|
end
|
115
113
|
|
116
|
-
if
|
117
|
-
if
|
114
|
+
if before_offset && after_offset
|
115
|
+
if after_offset < before_offset
|
118
116
|
# Get the number of items between the two cursors
|
119
|
-
space_between =
|
117
|
+
space_between = before_offset - after_offset - 1
|
120
118
|
paginated_nodes = set_limit(paginated_nodes, space_between)
|
121
119
|
else
|
122
120
|
# TODO I think this is untested
|
123
121
|
# The cursors overextend one another to an empty set
|
124
122
|
paginated_nodes = null_relation(paginated_nodes)
|
125
123
|
end
|
126
|
-
elsif
|
124
|
+
elsif before_offset
|
127
125
|
# Use limit to cut off the tail of the relation
|
128
|
-
paginated_nodes = set_limit(paginated_nodes,
|
126
|
+
paginated_nodes = set_limit(paginated_nodes, before_offset - 1)
|
129
127
|
end
|
130
128
|
|
131
129
|
paginated_nodes
|
132
130
|
end
|
133
131
|
end
|
134
132
|
|
133
|
+
# @return [Integer, nil]
|
134
|
+
def before_offset
|
135
|
+
@before_offset ||= before && offset_from_cursor(before)
|
136
|
+
end
|
137
|
+
|
138
|
+
# @return [Integer, nil]
|
139
|
+
def after_offset
|
140
|
+
@after_offset ||= after && offset_from_cursor(after)
|
141
|
+
end
|
142
|
+
|
135
143
|
# Apply `first` and `last` to `sliced_nodes`,
|
136
144
|
# returning a new relation
|
137
145
|
def limited_nodes
|
data/lib/graphql/query.rb
CHANGED
@@ -3,6 +3,7 @@ require "graphql/query/arguments"
|
|
3
3
|
require "graphql/query/arguments_cache"
|
4
4
|
require "graphql/query/context"
|
5
5
|
require "graphql/query/executor"
|
6
|
+
require "graphql/query/fingerprint"
|
6
7
|
require "graphql/query/literal_input"
|
7
8
|
require "graphql/query/null_context"
|
8
9
|
require "graphql/query/result"
|
@@ -106,7 +107,7 @@ module GraphQL
|
|
106
107
|
if variables.is_a?(String)
|
107
108
|
raise ArgumentError, "Query variables should be a Hash, not a String. Try JSON.parse to prepare variables."
|
108
109
|
else
|
109
|
-
@provided_variables = variables
|
110
|
+
@provided_variables = variables || {}
|
110
111
|
end
|
111
112
|
|
112
113
|
@query_string = query_string || query
|
@@ -265,6 +266,32 @@ module GraphQL
|
|
265
266
|
}
|
266
267
|
end
|
267
268
|
|
269
|
+
# This contains a few components:
|
270
|
+
#
|
271
|
+
# - The selected operation name (or `anonymous`)
|
272
|
+
# - The fingerprint of the query string
|
273
|
+
# - The number of given variables (for readability)
|
274
|
+
# - The fingerprint of the given variables
|
275
|
+
#
|
276
|
+
# This fingerprint can be used to track runs of the same operation-variables combination over time.
|
277
|
+
#
|
278
|
+
# @see operation_fingerprint
|
279
|
+
# @see variables_fingerprint
|
280
|
+
# @return [String] An opaque hash identifying this operation-variables combination
|
281
|
+
def fingerprint
|
282
|
+
@fingerprint ||= "#{operation_fingerprint}/#{variables_fingerprint}"
|
283
|
+
end
|
284
|
+
|
285
|
+
# @return [String] An opaque hash for identifying this query's given query string and selected operation
|
286
|
+
def operation_fingerprint
|
287
|
+
@operation_fingerprint ||= "#{selected_operation_name || "anonymous"}/#{Fingerprint.generate(query_string)}"
|
288
|
+
end
|
289
|
+
|
290
|
+
# @return [String] An opaque hash for identifying this query's given a variable values (not including defaults)
|
291
|
+
def variables_fingerprint
|
292
|
+
@variables_fingerprint ||= "#{provided_variables.size}/#{Fingerprint.generate(provided_variables.to_json)}"
|
293
|
+
end
|
294
|
+
|
268
295
|
def validation_pipeline
|
269
296
|
with_prepared_ast { @validation_pipeline }
|
270
297
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
class Query
|
5
|
+
# @api private
|
6
|
+
# @see Query#query_fingerprint
|
7
|
+
# @see Query#variables_fingerprint
|
8
|
+
# @see Query#fingerprint
|
9
|
+
module Fingerprint
|
10
|
+
# Make an obfuscated hash of the given string (either a query string or variables JSON)
|
11
|
+
# @param string [String]
|
12
|
+
# @return [String] A normalized, opaque hash
|
13
|
+
def self.generate(input_str)
|
14
|
+
# Implemented to be:
|
15
|
+
# - Short (and uniform) length
|
16
|
+
# - Stable
|
17
|
+
# - Irreversibly Opaque (don't want to leak variable values)
|
18
|
+
# - URL-friendly
|
19
|
+
bytes = Digest::SHA256.digest(input_str)
|
20
|
+
Base64.urlsafe_encode64(bytes)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/graphql/rake_task.rb
CHANGED
@@ -76,15 +76,7 @@ module GraphQL
|
|
76
76
|
# Set the parameters of this task by passing keyword arguments
|
77
77
|
# or assigning attributes inside the block
|
78
78
|
def initialize(options = {})
|
79
|
-
|
80
|
-
[:environment]
|
81
|
-
else
|
82
|
-
[]
|
83
|
-
end
|
84
|
-
|
85
|
-
all_options = DEFAULT_OPTIONS
|
86
|
-
.merge(dependencies: default_dependencies)
|
87
|
-
.merge(options)
|
79
|
+
all_options = DEFAULT_OPTIONS.merge(options)
|
88
80
|
all_options.each do |k, v|
|
89
81
|
self.public_send("#{k}=", v)
|
90
82
|
end
|
@@ -117,18 +109,26 @@ module GraphQL
|
|
117
109
|
File.join(@directory, @json_outfile)
|
118
110
|
end
|
119
111
|
|
112
|
+
def load_rails_environment_if_defined
|
113
|
+
if Rake::Task.task_defined?('environment')
|
114
|
+
Rake::Task['environment'].invoke
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
120
118
|
# Use the Rake DSL to add tasks
|
121
119
|
def define_task
|
122
120
|
namespace(@namespace) do
|
123
121
|
namespace("schema") do
|
124
122
|
desc("Dump the schema to IDL in #{idl_path}")
|
125
123
|
task :idl => @dependencies do
|
124
|
+
load_rails_environment_if_defined
|
126
125
|
write_outfile(:to_definition, idl_path)
|
127
126
|
puts "Schema IDL dumped into #{idl_path}"
|
128
127
|
end
|
129
128
|
|
130
129
|
desc("Dump the schema to JSON in #{json_path}")
|
131
130
|
task :json => @dependencies do
|
131
|
+
load_rails_environment_if_defined
|
132
132
|
write_outfile(:to_json, json_path)
|
133
133
|
puts "Schema JSON dumped into #{json_path}"
|
134
134
|
end
|
data/lib/graphql/schema.rb
CHANGED
@@ -96,6 +96,67 @@ module GraphQL
|
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
99
|
+
module LazyHandlingMethods
|
100
|
+
# Call the given block at the right time, either:
|
101
|
+
# - Right away, if `value` is not registered with `lazy_resolve`
|
102
|
+
# - After resolving `value`, if it's registered with `lazy_resolve` (eg, `Promise`)
|
103
|
+
# @api private
|
104
|
+
def after_lazy(value)
|
105
|
+
if lazy?(value)
|
106
|
+
GraphQL::Execution::Lazy.new do
|
107
|
+
result = sync_lazy(value)
|
108
|
+
# The returned result might also be lazy, so check it, too
|
109
|
+
after_lazy(result) do |final_result|
|
110
|
+
yield(final_result) if block_given?
|
111
|
+
end
|
112
|
+
end
|
113
|
+
else
|
114
|
+
yield(value) if block_given?
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Override this method to handle lazy objects in a custom way.
|
119
|
+
# @param value [Object] an instance of a class registered with {.lazy_resolve}
|
120
|
+
# @return [Object] A GraphQL-ready (non-lazy) object
|
121
|
+
# @api private
|
122
|
+
def sync_lazy(value)
|
123
|
+
lazy_method = lazy_method_name(value)
|
124
|
+
if lazy_method
|
125
|
+
synced_value = value.public_send(lazy_method)
|
126
|
+
sync_lazy(synced_value)
|
127
|
+
else
|
128
|
+
value
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# @return [Symbol, nil] The method name to lazily resolve `obj`, or nil if `obj`'s class wasn't registered wtih {#lazy_resolve}.
|
133
|
+
def lazy_method_name(obj)
|
134
|
+
lazy_methods.get(obj)
|
135
|
+
end
|
136
|
+
|
137
|
+
# @return [Boolean] True if this object should be lazily resolved
|
138
|
+
def lazy?(obj)
|
139
|
+
!!lazy_method_name(obj)
|
140
|
+
end
|
141
|
+
|
142
|
+
# Return a lazy if any of `maybe_lazies` are lazy,
|
143
|
+
# otherwise, call the block eagerly and return the result.
|
144
|
+
# @param maybe_lazies [Array]
|
145
|
+
# @api private
|
146
|
+
def after_any_lazies(maybe_lazies)
|
147
|
+
if maybe_lazies.any? { |l| lazy?(l) }
|
148
|
+
GraphQL::Execution::Lazy.all(maybe_lazies).then do |result|
|
149
|
+
yield
|
150
|
+
end
|
151
|
+
else
|
152
|
+
yield
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
include LazyHandlingMethods
|
158
|
+
extend LazyHandlingMethods
|
159
|
+
|
99
160
|
accepts_definitions \
|
100
161
|
:query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
|
101
162
|
:max_depth, :max_complexity, :default_max_page_size,
|
@@ -740,16 +801,6 @@ module GraphQL
|
|
740
801
|
# Error that is raised when [#Schema#from_definition] is passed an invalid schema definition string.
|
741
802
|
class InvalidDocumentError < Error; end;
|
742
803
|
|
743
|
-
# @return [Symbol, nil] The method name to lazily resolve `obj`, or nil if `obj`'s class wasn't registered wtih {#lazy_resolve}.
|
744
|
-
def lazy_method_name(obj)
|
745
|
-
@lazy_methods.get(obj)
|
746
|
-
end
|
747
|
-
|
748
|
-
# @return [Boolean] True if this object should be lazily resolved
|
749
|
-
def lazy?(obj)
|
750
|
-
!!lazy_method_name(obj)
|
751
|
-
end
|
752
|
-
|
753
804
|
# Return the GraphQL IDL for the schema
|
754
805
|
# @param context [Hash]
|
755
806
|
# @param only [<#call(member, ctx)>]
|
@@ -1582,48 +1633,6 @@ module GraphQL
|
|
1582
1633
|
end
|
1583
1634
|
end
|
1584
1635
|
|
1585
|
-
# Call the given block at the right time, either:
|
1586
|
-
# - Right away, if `value` is not registered with `lazy_resolve`
|
1587
|
-
# - After resolving `value`, if it's registered with `lazy_resolve` (eg, `Promise`)
|
1588
|
-
# @api private
|
1589
|
-
def after_lazy(value)
|
1590
|
-
if lazy?(value)
|
1591
|
-
GraphQL::Execution::Lazy.new do
|
1592
|
-
result = sync_lazy(value)
|
1593
|
-
# The returned result might also be lazy, so check it, too
|
1594
|
-
after_lazy(result) do |final_result|
|
1595
|
-
yield(final_result) if block_given?
|
1596
|
-
end
|
1597
|
-
end
|
1598
|
-
else
|
1599
|
-
yield(value) if block_given?
|
1600
|
-
end
|
1601
|
-
end
|
1602
|
-
|
1603
|
-
# Override this method to handle lazy objects in a custom way.
|
1604
|
-
# @param value [Object] an instance of a class registered with {.lazy_resolve}
|
1605
|
-
# @param ctx [GraphQL::Query::Context] the context for this query
|
1606
|
-
# @return [Object] A GraphQL-ready (non-lazy) object
|
1607
|
-
def sync_lazy(value)
|
1608
|
-
lazy_method = lazy_method_name(value)
|
1609
|
-
if lazy_method
|
1610
|
-
synced_value = value.public_send(lazy_method)
|
1611
|
-
sync_lazy(synced_value)
|
1612
|
-
else
|
1613
|
-
value
|
1614
|
-
end
|
1615
|
-
end
|
1616
|
-
|
1617
|
-
# @return [Symbol, nil] The method name to lazily resolve `obj`, or nil if `obj`'s class wasn't registered wtih {#lazy_resolve}.
|
1618
|
-
def lazy_method_name(obj)
|
1619
|
-
lazy_methods.get(obj)
|
1620
|
-
end
|
1621
|
-
|
1622
|
-
# @return [Boolean] True if this object should be lazily resolved
|
1623
|
-
def lazy?(obj)
|
1624
|
-
!!lazy_method_name(obj)
|
1625
|
-
end
|
1626
|
-
|
1627
1636
|
private
|
1628
1637
|
|
1629
1638
|
def lazy_methods
|
@@ -1756,16 +1765,24 @@ module GraphQL
|
|
1756
1765
|
}
|
1757
1766
|
own_possible_types[owner.graphql_name] = owner.possible_types
|
1758
1767
|
elsif type.kind.interface? && owner.kind.object?
|
1759
|
-
new_interfaces =
|
1760
|
-
|
1761
|
-
|
1762
|
-
|
1763
|
-
|
1768
|
+
new_interfaces = []
|
1769
|
+
owner.interfaces.each do |int_t|
|
1770
|
+
if int_t.is_a?(String) && int_t == type.graphql_name
|
1771
|
+
new_interfaces << type
|
1772
|
+
elsif int_t.is_a?(LateBoundType) && int_t.graphql_name == type.graphql_name
|
1773
|
+
new_interfaces << type
|
1764
1774
|
else
|
1765
|
-
t
|
1775
|
+
# Don't re-add proper interface definitions,
|
1776
|
+
# they were probably already added, maybe with options.
|
1766
1777
|
end
|
1767
1778
|
end
|
1768
1779
|
owner.implements(*new_interfaces)
|
1780
|
+
new_interfaces.each do |int|
|
1781
|
+
pt = own_possible_types[int.graphql_name] ||= []
|
1782
|
+
if !pt.include?(owner)
|
1783
|
+
pt << owner
|
1784
|
+
end
|
1785
|
+
end
|
1769
1786
|
end
|
1770
1787
|
|
1771
1788
|
when nil
|
@@ -1864,46 +1881,27 @@ module GraphQL
|
|
1864
1881
|
end
|
1865
1882
|
if type.kind.object?
|
1866
1883
|
own_possible_types[type.graphql_name] = [type]
|
1867
|
-
type.
|
1868
|
-
|
1869
|
-
|
1870
|
-
|
1884
|
+
type.interface_type_memberships.each do |interface_type_membership|
|
1885
|
+
case interface_type_membership
|
1886
|
+
when Schema::TypeMembership
|
1887
|
+
interface_type = interface_type_membership.abstract_type
|
1888
|
+
# We can get these now; we'll have to get late-bound types later
|
1889
|
+
if interface_type.is_a?(Module)
|
1890
|
+
implementers = own_possible_types[interface_type.graphql_name] ||= []
|
1891
|
+
implementers << type
|
1892
|
+
end
|
1893
|
+
when String, Schema::LateBoundType
|
1894
|
+
interface_type = interface_type_membership
|
1895
|
+
else
|
1896
|
+
raise ArgumentError, "Invariant: unexpected type membership for #{type.graphql_name}: #{interface_type_membership.class} (#{interface_type_membership.inspect})"
|
1897
|
+
end
|
1898
|
+
add_type(interface_type, owner: type, late_types: late_types, path: path + ["implements"])
|
1871
1899
|
end
|
1872
1900
|
end
|
1873
1901
|
end
|
1874
1902
|
end
|
1875
1903
|
end
|
1876
1904
|
|
1877
|
-
# Call the given block at the right time, either:
|
1878
|
-
# - Right away, if `value` is not registered with `lazy_resolve`
|
1879
|
-
# - After resolving `value`, if it's registered with `lazy_resolve` (eg, `Promise`)
|
1880
|
-
# @api private
|
1881
|
-
def after_lazy(value)
|
1882
|
-
if lazy?(value)
|
1883
|
-
GraphQL::Execution::Lazy.new do
|
1884
|
-
result = sync_lazy(value)
|
1885
|
-
# The returned result might also be lazy, so check it, too
|
1886
|
-
after_lazy(result) do |final_result|
|
1887
|
-
yield(final_result) if block_given?
|
1888
|
-
end
|
1889
|
-
end
|
1890
|
-
else
|
1891
|
-
yield(value) if block_given?
|
1892
|
-
end
|
1893
|
-
end
|
1894
|
-
|
1895
|
-
# @see Schema.sync_lazy for a hook to override
|
1896
|
-
# @api private
|
1897
|
-
def sync_lazy(value)
|
1898
|
-
lazy_method = lazy_method_name(value)
|
1899
|
-
if lazy_method
|
1900
|
-
synced_value = value.public_send(lazy_method)
|
1901
|
-
sync_lazy(synced_value)
|
1902
|
-
else
|
1903
|
-
value
|
1904
|
-
end
|
1905
|
-
end
|
1906
|
-
|
1907
1905
|
protected
|
1908
1906
|
|
1909
1907
|
def rescues?
|
data/lib/graphql/schema/field.rb
CHANGED
@@ -173,7 +173,7 @@ module GraphQL
|
|
173
173
|
# @param resolver_method [Symbol] The method on the type to call to resolve this field (defaults to `name`)
|
174
174
|
# @param connection [Boolean] `true` if this field should get automagic connection behavior; default is to infer by `*Connection` in the return type name
|
175
175
|
# @param connection_extension [Class] The extension to add, to implement connections. If `nil`, no extension is added.
|
176
|
-
# @param max_page_size [Integer] For connections, the maximum number of items to return from this field
|
176
|
+
# @param max_page_size [Integer, nil] For connections, the maximum number of items to return from this field, or `nil` to allow unlimited results.
|
177
177
|
# @param introspection [Boolean] If true, this field will be marked as `#introspection?` and the name may begin with `__`
|
178
178
|
# @param resolve [<#call(obj, args, ctx)>] **deprecated** for compatibility with <1.8.0
|
179
179
|
# @param field [GraphQL::Field, GraphQL::Schema::Field] **deprecated** for compatibility with <1.8.0
|
@@ -188,7 +188,7 @@ module GraphQL
|
|
188
188
|
# @param trace [Boolean] If true, a {GraphQL::Tracing} tracer will measure this scalar field
|
189
189
|
# @param ast_node [Language::Nodes::FieldDefinition, nil] If this schema was parsed from definition, this AST node defined the field
|
190
190
|
# @param method_conflict_warning [Boolean] If false, skip the warning if this field's method conflicts with a built-in method
|
191
|
-
def initialize(type: nil, name: nil, owner: nil, null: nil, field: nil, function: nil, description: nil, deprecation_reason: nil, method: nil, hash_key: nil, resolver_method: nil, resolve: nil, connection: nil, max_page_size:
|
191
|
+
def initialize(type: nil, name: nil, owner: nil, null: nil, field: nil, function: nil, description: nil, deprecation_reason: nil, method: nil, hash_key: nil, resolver_method: nil, resolve: nil, connection: nil, max_page_size: :not_given, scope: nil, introspection: false, camelize: true, trace: nil, complexity: 1, ast_node: nil, extras: [], extensions: EMPTY_ARRAY, connection_extension: self.class.connection_extension, resolver_class: nil, subscription_scope: nil, relay_node_field: false, relay_nodes_field: false, method_conflict_warning: true, arguments: EMPTY_HASH, &definition_block)
|
192
192
|
if name.nil?
|
193
193
|
raise ArgumentError, "missing first `name` argument or keyword `name:`"
|
194
194
|
end
|
@@ -242,7 +242,8 @@ module GraphQL
|
|
242
242
|
@return_type_expr = type
|
243
243
|
@return_type_null = null
|
244
244
|
@connection = connection
|
245
|
-
@
|
245
|
+
@has_max_page_size = max_page_size != :not_given
|
246
|
+
@max_page_size = max_page_size == :not_given ? nil : max_page_size
|
246
247
|
@introspection = introspection
|
247
248
|
@extras = extras
|
248
249
|
@resolver_class = resolver_class
|
@@ -381,7 +382,12 @@ module GraphQL
|
|
381
382
|
end
|
382
383
|
end
|
383
384
|
|
384
|
-
# @return [
|
385
|
+
# @return [Boolean] True if this field's {#max_page_size} should override the schema default.
|
386
|
+
def has_max_page_size?
|
387
|
+
@has_max_page_size
|
388
|
+
end
|
389
|
+
|
390
|
+
# @return [Integer, nil] Applied to connections if {#has_max_page_size?}
|
385
391
|
attr_reader :max_page_size
|
386
392
|
|
387
393
|
# @return [GraphQL::Field]
|
@@ -646,22 +652,34 @@ module GraphQL
|
|
646
652
|
if graphql_args.any? || @extras.any?
|
647
653
|
# Splat the GraphQL::Arguments to Ruby keyword arguments
|
648
654
|
ruby_kwargs = graphql_args.to_kwargs
|
655
|
+
maybe_lazies = []
|
649
656
|
# Apply any `prepare` methods. Not great code organization, can this go somewhere better?
|
650
657
|
arguments.each do |name, arg_defn|
|
651
658
|
ruby_kwargs_key = arg_defn.keyword
|
652
659
|
|
653
|
-
|
654
|
-
|
660
|
+
if ruby_kwargs.key?(ruby_kwargs_key)
|
661
|
+
loads = arg_defn.loads
|
655
662
|
value = ruby_kwargs[ruby_kwargs_key]
|
656
|
-
|
657
|
-
|
663
|
+
loaded_value = if loads && !arg_defn.from_resolver?
|
664
|
+
if arg_defn.type.list?
|
665
|
+
loaded_values = value.map { |val| load_application_object(arg_defn, loads, val, field_ctx.query.context) }
|
666
|
+
maybe_lazies.concat(loaded_values)
|
667
|
+
else
|
668
|
+
load_application_object(arg_defn, loads, value, field_ctx.query.context)
|
669
|
+
end
|
658
670
|
else
|
659
|
-
|
671
|
+
value
|
660
672
|
end
|
661
|
-
end
|
662
673
|
|
663
|
-
|
664
|
-
|
674
|
+
maybe_lazies << field_ctx.schema.after_lazy(loaded_value) do |loaded_value|
|
675
|
+
prepared_value = if arg_defn.prepare
|
676
|
+
arg_defn.prepare_value(obj, loaded_value)
|
677
|
+
else
|
678
|
+
loaded_value
|
679
|
+
end
|
680
|
+
|
681
|
+
ruby_kwargs[ruby_kwargs_key] = prepared_value
|
682
|
+
end
|
665
683
|
end
|
666
684
|
end
|
667
685
|
|
@@ -669,7 +687,9 @@ module GraphQL
|
|
669
687
|
ruby_kwargs[extra_arg] = fetch_extra(extra_arg, field_ctx)
|
670
688
|
end
|
671
689
|
|
672
|
-
|
690
|
+
field_ctx.schema.after_any_lazies(maybe_lazies) do
|
691
|
+
ruby_kwargs
|
692
|
+
end
|
673
693
|
else
|
674
694
|
NO_ARGS
|
675
695
|
end
|