graphql 1.12.7 → 1.12.12
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_generator.rb +1 -1
- data/lib/generators/graphql/templates/graphql_controller.erb +2 -2
- data/lib/graphql.rb +10 -10
- data/lib/graphql/backtrace/table.rb +14 -2
- data/lib/graphql/dataloader.rb +59 -15
- data/lib/graphql/dataloader/null_dataloader.rb +1 -0
- data/lib/graphql/execution/errors.rb +4 -4
- data/lib/graphql/execution/execute.rb +1 -1
- data/lib/graphql/execution/interpreter.rb +4 -8
- data/lib/graphql/execution/interpreter/arguments_cache.rb +3 -2
- data/lib/graphql/execution/interpreter/runtime.rb +382 -223
- data/lib/graphql/introspection/schema_type.rb +1 -1
- data/lib/graphql/pagination/connections.rb +1 -1
- data/lib/graphql/query/null_context.rb +7 -1
- data/lib/graphql/rake_task.rb +3 -0
- data/lib/graphql/schema.rb +44 -218
- data/lib/graphql/schema/addition.rb +238 -0
- data/lib/graphql/schema/argument.rb +55 -36
- data/lib/graphql/schema/directive/transform.rb +13 -1
- data/lib/graphql/schema/input_object.rb +2 -2
- data/lib/graphql/schema/loader.rb +8 -0
- data/lib/graphql/schema/member/base_dsl_methods.rb +3 -15
- data/lib/graphql/schema/object.rb +19 -5
- data/lib/graphql/schema/resolver.rb +46 -24
- data/lib/graphql/schema/scalar.rb +3 -1
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +17 -8
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +1 -1
- data/lib/graphql/static_validation/validator.rb +5 -0
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +4 -3
- data/lib/graphql/subscriptions/serialize.rb +11 -1
- data/lib/graphql/version.rb +1 -1
- metadata +17 -3
- data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
@@ -79,7 +79,7 @@ module GraphQL
|
|
79
79
|
context: context,
|
80
80
|
parent: parent,
|
81
81
|
field: field,
|
82
|
-
max_page_size: field.max_page_size
|
82
|
+
max_page_size: field.has_max_page_size? ? field.max_page_size : context.schema.default_max_page_size,
|
83
83
|
first: arguments[:first],
|
84
84
|
after: arguments[:after],
|
85
85
|
last: arguments[:last],
|
@@ -9,10 +9,16 @@ module GraphQL
|
|
9
9
|
def visible_type?(t); true; end
|
10
10
|
end
|
11
11
|
|
12
|
+
class NullQuery
|
13
|
+
def with_error_handling
|
14
|
+
yield
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
12
18
|
attr_reader :schema, :query, :warden, :dataloader
|
13
19
|
|
14
20
|
def initialize
|
15
|
-
@query =
|
21
|
+
@query = NullQuery.new
|
16
22
|
@dataloader = GraphQL::Dataloader::NullDataloader.new
|
17
23
|
@schema = GraphQL::Schema.new
|
18
24
|
@warden = NullWarden.new(
|
data/lib/graphql/rake_task.rb
CHANGED
@@ -98,6 +98,9 @@ module GraphQL
|
|
98
98
|
result = schema.public_send(method_name, only: @only, except: @except, context: context)
|
99
99
|
dir = File.dirname(file)
|
100
100
|
FileUtils.mkdir_p(dir)
|
101
|
+
if !result.end_with?("\n")
|
102
|
+
result += "\n"
|
103
|
+
end
|
101
104
|
File.write(file, result)
|
102
105
|
end
|
103
106
|
|
data/lib/graphql/schema.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
require "graphql/schema/addition"
|
2
3
|
require "graphql/schema/base_64_encoder"
|
3
4
|
require "graphql/schema/catchall_middleware"
|
4
5
|
require "graphql/schema/default_parse_error"
|
@@ -355,23 +356,6 @@ module GraphQL
|
|
355
356
|
# For forwards-compatibility with Schema classes
|
356
357
|
alias :graphql_definition :itself
|
357
358
|
|
358
|
-
# Validate a query string according to this schema.
|
359
|
-
# @param string_or_document [String, GraphQL::Language::Nodes::Document]
|
360
|
-
# @return [Array<GraphQL::StaticValidation::Error >]
|
361
|
-
def validate(string_or_document, rules: nil, context: nil)
|
362
|
-
doc = if string_or_document.is_a?(String)
|
363
|
-
GraphQL.parse(string_or_document)
|
364
|
-
else
|
365
|
-
string_or_document
|
366
|
-
end
|
367
|
-
query = GraphQL::Query.new(self, document: doc, context: context)
|
368
|
-
validator_opts = { schema: self }
|
369
|
-
rules && (validator_opts[:rules] = rules)
|
370
|
-
validator = GraphQL::StaticValidation::Validator.new(**validator_opts)
|
371
|
-
res = validator.validate(query, timeout: validate_timeout)
|
372
|
-
res[:errors]
|
373
|
-
end
|
374
|
-
|
375
359
|
def deprecated_define(**kwargs, &block)
|
376
360
|
super
|
377
361
|
ensure_defined
|
@@ -712,6 +696,7 @@ module GraphQL
|
|
712
696
|
def_delegators :_schema_class, :unauthorized_object, :unauthorized_field, :inaccessible_fields
|
713
697
|
def_delegators :_schema_class, :directive
|
714
698
|
def_delegators :_schema_class, :error_handler
|
699
|
+
def_delegators :_schema_class, :validate
|
715
700
|
|
716
701
|
|
717
702
|
# Given this schema member, find the class-based definition object
|
@@ -861,7 +846,6 @@ module GraphQL
|
|
861
846
|
def_delegators :graphql_definition,
|
862
847
|
# Execution
|
863
848
|
:execution_strategy_for_operation,
|
864
|
-
:validate,
|
865
849
|
# Configuration
|
866
850
|
:metadata, :redefine,
|
867
851
|
:id_from_object_proc, :object_from_id_proc,
|
@@ -1293,6 +1277,23 @@ module GraphQL
|
|
1293
1277
|
end
|
1294
1278
|
end
|
1295
1279
|
|
1280
|
+
# Validate a query string according to this schema.
|
1281
|
+
# @param string_or_document [String, GraphQL::Language::Nodes::Document]
|
1282
|
+
# @return [Array<GraphQL::StaticValidation::Error >]
|
1283
|
+
def validate(string_or_document, rules: nil, context: nil)
|
1284
|
+
doc = if string_or_document.is_a?(String)
|
1285
|
+
GraphQL.parse(string_or_document)
|
1286
|
+
else
|
1287
|
+
string_or_document
|
1288
|
+
end
|
1289
|
+
query = GraphQL::Query.new(self, document: doc, context: context)
|
1290
|
+
validator_opts = { schema: self }
|
1291
|
+
rules && (validator_opts[:rules] = rules)
|
1292
|
+
validator = GraphQL::StaticValidation::Validator.new(**validator_opts)
|
1293
|
+
res = validator.validate(query, timeout: validate_timeout)
|
1294
|
+
res[:errors]
|
1295
|
+
end
|
1296
|
+
|
1296
1297
|
attr_writer :max_complexity
|
1297
1298
|
|
1298
1299
|
def max_complexity(max_complexity = nil)
|
@@ -1582,10 +1583,7 @@ module GraphQL
|
|
1582
1583
|
# @param new_directive [Class]
|
1583
1584
|
# @return void
|
1584
1585
|
def directive(new_directive)
|
1585
|
-
|
1586
|
-
add_type_and_traverse(new_directive, root: false)
|
1587
|
-
new_directive
|
1588
|
-
end
|
1586
|
+
add_type_and_traverse(new_directive, root: false)
|
1589
1587
|
end
|
1590
1588
|
|
1591
1589
|
def default_directives
|
@@ -1709,6 +1707,30 @@ module GraphQL
|
|
1709
1707
|
|
1710
1708
|
private
|
1711
1709
|
|
1710
|
+
# @param t [Module, Array<Module>]
|
1711
|
+
# @return [void]
|
1712
|
+
def add_type_and_traverse(t, root:)
|
1713
|
+
if root
|
1714
|
+
@root_types ||= []
|
1715
|
+
@root_types << t
|
1716
|
+
end
|
1717
|
+
new_types = Array(t)
|
1718
|
+
addition = Schema::Addition.new(schema: self, own_types: own_types, new_types: new_types)
|
1719
|
+
own_types.merge!(addition.types)
|
1720
|
+
own_possible_types.merge!(addition.possible_types) { |key, old_val, new_val| old_val + new_val }
|
1721
|
+
own_union_memberships.merge!(addition.union_memberships)
|
1722
|
+
|
1723
|
+
addition.references.each { |thing, pointers|
|
1724
|
+
pointers.each { |pointer| references_to(thing, from: pointer) }
|
1725
|
+
}
|
1726
|
+
|
1727
|
+
addition.directives.each { |dir_class| own_directives[dir_class.graphql_name] = dir_class }
|
1728
|
+
|
1729
|
+
addition.arguments_with_default_values.each do |arg|
|
1730
|
+
arg.validate_default_value
|
1731
|
+
end
|
1732
|
+
end
|
1733
|
+
|
1712
1734
|
def lazy_methods
|
1713
1735
|
if !defined?(@lazy_methods)
|
1714
1736
|
if inherited_map = find_inherited_value(:lazy_methods)
|
@@ -1774,202 +1796,6 @@ module GraphQL
|
|
1774
1796
|
def own_multiplex_analyzers
|
1775
1797
|
@own_multiplex_analyzers ||= []
|
1776
1798
|
end
|
1777
|
-
|
1778
|
-
# @param t [Module, Array<Module>]
|
1779
|
-
# @return [void]
|
1780
|
-
def add_type_and_traverse(t, root:)
|
1781
|
-
if root
|
1782
|
-
@root_types ||= []
|
1783
|
-
@root_types << t
|
1784
|
-
end
|
1785
|
-
late_types = []
|
1786
|
-
new_types = Array(t)
|
1787
|
-
new_types.each { |t| add_type(t, owner: nil, late_types: late_types, path: [t.graphql_name]) }
|
1788
|
-
missed_late_types = 0
|
1789
|
-
while (late_type_vals = late_types.shift)
|
1790
|
-
type_owner, lt = late_type_vals
|
1791
|
-
if lt.is_a?(String)
|
1792
|
-
type = Member::BuildType.constantize(lt)
|
1793
|
-
# Reset the counter, since we might succeed next go-round
|
1794
|
-
missed_late_types = 0
|
1795
|
-
update_type_owner(type_owner, type)
|
1796
|
-
add_type(type, owner: type_owner, late_types: late_types, path: [type.graphql_name])
|
1797
|
-
elsif lt.is_a?(LateBoundType)
|
1798
|
-
if (type = get_type(lt.graphql_name))
|
1799
|
-
# Reset the counter, since we might succeed next go-round
|
1800
|
-
missed_late_types = 0
|
1801
|
-
update_type_owner(type_owner, type)
|
1802
|
-
add_type(type, owner: type_owner, late_types: late_types, path: [type.graphql_name])
|
1803
|
-
else
|
1804
|
-
missed_late_types += 1
|
1805
|
-
# Add it back to the list, maybe we'll be able to resolve it later.
|
1806
|
-
late_types << [type_owner, lt]
|
1807
|
-
if missed_late_types == late_types.size
|
1808
|
-
# We've looked at all of them and haven't resolved one.
|
1809
|
-
raise UnresolvedLateBoundTypeError.new(type: lt)
|
1810
|
-
else
|
1811
|
-
# Try the next one
|
1812
|
-
end
|
1813
|
-
end
|
1814
|
-
else
|
1815
|
-
raise ArgumentError, "Unexpected late type: #{lt.inspect}"
|
1816
|
-
end
|
1817
|
-
end
|
1818
|
-
nil
|
1819
|
-
end
|
1820
|
-
|
1821
|
-
def update_type_owner(owner, type)
|
1822
|
-
case owner
|
1823
|
-
when Class
|
1824
|
-
if owner.kind.union?
|
1825
|
-
# It's a union with possible_types
|
1826
|
-
# Replace the item by class name
|
1827
|
-
owner.assign_type_membership_object_type(type)
|
1828
|
-
own_possible_types[owner.graphql_name] = owner.possible_types
|
1829
|
-
elsif type.kind.interface? && owner.kind.object?
|
1830
|
-
new_interfaces = []
|
1831
|
-
owner.interfaces.each do |int_t|
|
1832
|
-
if int_t.is_a?(String) && int_t == type.graphql_name
|
1833
|
-
new_interfaces << type
|
1834
|
-
elsif int_t.is_a?(LateBoundType) && int_t.graphql_name == type.graphql_name
|
1835
|
-
new_interfaces << type
|
1836
|
-
else
|
1837
|
-
# Don't re-add proper interface definitions,
|
1838
|
-
# they were probably already added, maybe with options.
|
1839
|
-
end
|
1840
|
-
end
|
1841
|
-
owner.implements(*new_interfaces)
|
1842
|
-
new_interfaces.each do |int|
|
1843
|
-
pt = own_possible_types[int.graphql_name] ||= []
|
1844
|
-
if !pt.include?(owner)
|
1845
|
-
pt << owner
|
1846
|
-
end
|
1847
|
-
end
|
1848
|
-
end
|
1849
|
-
|
1850
|
-
when nil
|
1851
|
-
# It's a root type
|
1852
|
-
own_types[type.graphql_name] = type
|
1853
|
-
when GraphQL::Schema::Field, GraphQL::Schema::Argument
|
1854
|
-
orig_type = owner.type
|
1855
|
-
# Apply list/non-null wrapper as needed
|
1856
|
-
if orig_type.respond_to?(:of_type)
|
1857
|
-
transforms = []
|
1858
|
-
while (orig_type.respond_to?(:of_type))
|
1859
|
-
if orig_type.kind.non_null?
|
1860
|
-
transforms << :to_non_null_type
|
1861
|
-
elsif orig_type.kind.list?
|
1862
|
-
transforms << :to_list_type
|
1863
|
-
else
|
1864
|
-
raise "Invariant: :of_type isn't non-null or list"
|
1865
|
-
end
|
1866
|
-
orig_type = orig_type.of_type
|
1867
|
-
end
|
1868
|
-
transforms.reverse_each { |t| type = type.public_send(t) }
|
1869
|
-
end
|
1870
|
-
owner.type = type
|
1871
|
-
else
|
1872
|
-
raise "Unexpected update: #{owner.inspect} #{type.inspect}"
|
1873
|
-
end
|
1874
|
-
end
|
1875
|
-
|
1876
|
-
def add_type(type, owner:, late_types:, path:)
|
1877
|
-
if type.respond_to?(:metadata) && type.metadata.is_a?(Hash)
|
1878
|
-
type_class = type.metadata[:type_class]
|
1879
|
-
if type_class.nil?
|
1880
|
-
raise ArgumentError, "Can't add legacy type: #{type} (#{type.class})"
|
1881
|
-
else
|
1882
|
-
type = type_class
|
1883
|
-
end
|
1884
|
-
elsif type.is_a?(String) || type.is_a?(GraphQL::Schema::LateBoundType)
|
1885
|
-
late_types << [owner, type]
|
1886
|
-
return
|
1887
|
-
end
|
1888
|
-
|
1889
|
-
if owner.is_a?(Class) && owner < GraphQL::Schema::Union
|
1890
|
-
um = own_union_memberships[type.graphql_name] ||= []
|
1891
|
-
um << owner
|
1892
|
-
end
|
1893
|
-
|
1894
|
-
if (prev_type = own_types[type.graphql_name])
|
1895
|
-
if prev_type != type
|
1896
|
-
raise DuplicateTypeNamesError.new(
|
1897
|
-
type_name: type.graphql_name,
|
1898
|
-
first_definition: prev_type,
|
1899
|
-
second_definition: type,
|
1900
|
-
path: path,
|
1901
|
-
)
|
1902
|
-
else
|
1903
|
-
# This type was already added
|
1904
|
-
end
|
1905
|
-
elsif type.is_a?(Class) && type < GraphQL::Schema::Directive
|
1906
|
-
type.arguments.each do |name, arg|
|
1907
|
-
arg_type = arg.type.unwrap
|
1908
|
-
references_to(arg_type, from: arg)
|
1909
|
-
add_type(arg_type, owner: arg, late_types: late_types, path: path + [name])
|
1910
|
-
end
|
1911
|
-
else
|
1912
|
-
own_types[type.graphql_name] = type
|
1913
|
-
add_directives_from(type)
|
1914
|
-
if type.kind.fields?
|
1915
|
-
type.fields.each do |name, field|
|
1916
|
-
field_type = field.type.unwrap
|
1917
|
-
references_to(field_type, from: field)
|
1918
|
-
field_path = path + [name]
|
1919
|
-
add_type(field_type, owner: field, late_types: late_types, path: field_path)
|
1920
|
-
add_directives_from(field)
|
1921
|
-
field.arguments.each do |arg_name, arg|
|
1922
|
-
add_directives_from(arg)
|
1923
|
-
arg_type = arg.type.unwrap
|
1924
|
-
references_to(arg_type, from: arg)
|
1925
|
-
add_type(arg_type, owner: arg, late_types: late_types, path: field_path + [arg_name])
|
1926
|
-
end
|
1927
|
-
end
|
1928
|
-
end
|
1929
|
-
if type.kind.input_object?
|
1930
|
-
type.arguments.each do |arg_name, arg|
|
1931
|
-
add_directives_from(arg)
|
1932
|
-
arg_type = arg.type.unwrap
|
1933
|
-
references_to(arg_type, from: arg)
|
1934
|
-
add_type(arg_type, owner: arg, late_types: late_types, path: path + [arg_name])
|
1935
|
-
end
|
1936
|
-
end
|
1937
|
-
if type.kind.union?
|
1938
|
-
own_possible_types[type.graphql_name] = type.possible_types
|
1939
|
-
type.possible_types.each do |t|
|
1940
|
-
add_type(t, owner: type, late_types: late_types, path: path + ["possible_types"])
|
1941
|
-
end
|
1942
|
-
end
|
1943
|
-
if type.kind.interface?
|
1944
|
-
type.orphan_types.each do |t|
|
1945
|
-
add_type(t, owner: type, late_types: late_types, path: path + ["orphan_types"])
|
1946
|
-
end
|
1947
|
-
end
|
1948
|
-
if type.kind.object?
|
1949
|
-
own_possible_types[type.graphql_name] = [type]
|
1950
|
-
type.interface_type_memberships.each do |interface_type_membership|
|
1951
|
-
case interface_type_membership
|
1952
|
-
when Schema::TypeMembership
|
1953
|
-
interface_type = interface_type_membership.abstract_type
|
1954
|
-
# We can get these now; we'll have to get late-bound types later
|
1955
|
-
if interface_type.is_a?(Module)
|
1956
|
-
implementers = own_possible_types[interface_type.graphql_name] ||= []
|
1957
|
-
implementers << type
|
1958
|
-
end
|
1959
|
-
when String, Schema::LateBoundType
|
1960
|
-
interface_type = interface_type_membership
|
1961
|
-
else
|
1962
|
-
raise ArgumentError, "Invariant: unexpected type membership for #{type.graphql_name}: #{interface_type_membership.class} (#{interface_type_membership.inspect})"
|
1963
|
-
end
|
1964
|
-
add_type(interface_type, owner: type, late_types: late_types, path: path + ["implements"])
|
1965
|
-
end
|
1966
|
-
end
|
1967
|
-
end
|
1968
|
-
end
|
1969
|
-
|
1970
|
-
def add_directives_from(owner)
|
1971
|
-
owner.directives.each { |dir| directive(dir.class) }
|
1972
|
-
end
|
1973
1799
|
end
|
1974
1800
|
|
1975
1801
|
def dataloader_class
|
@@ -0,0 +1,238 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
class Schema
|
5
|
+
class Addition
|
6
|
+
attr_reader :directives, :possible_types, :types, :union_memberships, :references, :arguments_with_default_values
|
7
|
+
|
8
|
+
def initialize(schema:, own_types:, new_types:)
|
9
|
+
@schema = schema
|
10
|
+
@own_types = own_types
|
11
|
+
@directives = Set.new
|
12
|
+
@possible_types = {}
|
13
|
+
@types = {}
|
14
|
+
@union_memberships = {}
|
15
|
+
@references = Hash.new { |h, k| h[k] = [] }
|
16
|
+
@arguments_with_default_values = []
|
17
|
+
add_type_and_traverse(new_types)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def references_to(thing, from:)
|
23
|
+
@references[thing] << from
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_type(name)
|
27
|
+
@types[name] || @schema.get_type(name)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Lookup using `own_types` here because it's ok to override
|
31
|
+
# inherited types by name
|
32
|
+
def get_local_type(name)
|
33
|
+
@types[name] || @own_types[name]
|
34
|
+
end
|
35
|
+
|
36
|
+
def add_directives_from(owner)
|
37
|
+
dirs = owner.directives.map(&:class)
|
38
|
+
@directives.merge(dirs)
|
39
|
+
add_type_and_traverse(dirs)
|
40
|
+
end
|
41
|
+
|
42
|
+
def add_type_and_traverse(new_types)
|
43
|
+
late_types = []
|
44
|
+
new_types.each { |t| add_type(t, owner: nil, late_types: late_types, path: [t.graphql_name]) }
|
45
|
+
missed_late_types = 0
|
46
|
+
while (late_type_vals = late_types.shift)
|
47
|
+
type_owner, lt = late_type_vals
|
48
|
+
if lt.is_a?(String)
|
49
|
+
type = Member::BuildType.constantize(lt)
|
50
|
+
# Reset the counter, since we might succeed next go-round
|
51
|
+
missed_late_types = 0
|
52
|
+
update_type_owner(type_owner, type)
|
53
|
+
add_type(type, owner: type_owner, late_types: late_types, path: [type.graphql_name])
|
54
|
+
elsif lt.is_a?(LateBoundType)
|
55
|
+
if (type = get_type(lt.name))
|
56
|
+
# Reset the counter, since we might succeed next go-round
|
57
|
+
missed_late_types = 0
|
58
|
+
update_type_owner(type_owner, type)
|
59
|
+
add_type(type, owner: type_owner, late_types: late_types, path: [type.graphql_name])
|
60
|
+
else
|
61
|
+
missed_late_types += 1
|
62
|
+
# Add it back to the list, maybe we'll be able to resolve it later.
|
63
|
+
late_types << [type_owner, lt]
|
64
|
+
if missed_late_types == late_types.size
|
65
|
+
# We've looked at all of them and haven't resolved one.
|
66
|
+
raise UnresolvedLateBoundTypeError.new(type: lt)
|
67
|
+
else
|
68
|
+
# Try the next one
|
69
|
+
end
|
70
|
+
end
|
71
|
+
else
|
72
|
+
raise ArgumentError, "Unexpected late type: #{lt.inspect}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
nil
|
76
|
+
end
|
77
|
+
|
78
|
+
def update_type_owner(owner, type)
|
79
|
+
case owner
|
80
|
+
when Class
|
81
|
+
if owner.kind.union?
|
82
|
+
# It's a union with possible_types
|
83
|
+
# Replace the item by class name
|
84
|
+
owner.assign_type_membership_object_type(type)
|
85
|
+
@possible_types[owner.graphql_name] = owner.possible_types
|
86
|
+
elsif type.kind.interface? && owner.kind.object?
|
87
|
+
new_interfaces = []
|
88
|
+
owner.interfaces.each do |int_t|
|
89
|
+
if int_t.is_a?(String) && int_t == type.graphql_name
|
90
|
+
new_interfaces << type
|
91
|
+
elsif int_t.is_a?(LateBoundType) && int_t.graphql_name == type.graphql_name
|
92
|
+
new_interfaces << type
|
93
|
+
else
|
94
|
+
# Don't re-add proper interface definitions,
|
95
|
+
# they were probably already added, maybe with options.
|
96
|
+
end
|
97
|
+
end
|
98
|
+
owner.implements(*new_interfaces)
|
99
|
+
new_interfaces.each do |int|
|
100
|
+
pt = @possible_types[int.graphql_name] ||= []
|
101
|
+
if !pt.include?(owner)
|
102
|
+
pt << owner
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
when nil
|
108
|
+
# It's a root type
|
109
|
+
@types[type.graphql_name] = type
|
110
|
+
when GraphQL::Schema::Field, GraphQL::Schema::Argument
|
111
|
+
orig_type = owner.type
|
112
|
+
# Apply list/non-null wrapper as needed
|
113
|
+
if orig_type.respond_to?(:of_type)
|
114
|
+
transforms = []
|
115
|
+
while (orig_type.respond_to?(:of_type))
|
116
|
+
if orig_type.kind.non_null?
|
117
|
+
transforms << :to_non_null_type
|
118
|
+
elsif orig_type.kind.list?
|
119
|
+
transforms << :to_list_type
|
120
|
+
else
|
121
|
+
raise "Invariant: :of_type isn't non-null or list"
|
122
|
+
end
|
123
|
+
orig_type = orig_type.of_type
|
124
|
+
end
|
125
|
+
transforms.reverse_each { |t| type = type.public_send(t) }
|
126
|
+
end
|
127
|
+
owner.type = type
|
128
|
+
else
|
129
|
+
raise "Unexpected update: #{owner.inspect} #{type.inspect}"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def add_type(type, owner:, late_types:, path:)
|
134
|
+
if type.respond_to?(:metadata) && type.metadata.is_a?(Hash)
|
135
|
+
type_class = type.metadata[:type_class]
|
136
|
+
if type_class.nil?
|
137
|
+
raise ArgumentError, "Can't add legacy type: #{type} (#{type.class})"
|
138
|
+
else
|
139
|
+
type = type_class
|
140
|
+
end
|
141
|
+
elsif type.is_a?(String) || type.is_a?(GraphQL::Schema::LateBoundType)
|
142
|
+
late_types << [owner, type]
|
143
|
+
return
|
144
|
+
end
|
145
|
+
|
146
|
+
if owner.is_a?(Class) && owner < GraphQL::Schema::Union
|
147
|
+
um = @union_memberships[type.graphql_name] ||= []
|
148
|
+
um << owner
|
149
|
+
end
|
150
|
+
|
151
|
+
if (prev_type = get_local_type(type.graphql_name))
|
152
|
+
if prev_type != type
|
153
|
+
raise DuplicateTypeNamesError.new(
|
154
|
+
type_name: type.graphql_name,
|
155
|
+
first_definition: prev_type,
|
156
|
+
second_definition: type,
|
157
|
+
path: path,
|
158
|
+
)
|
159
|
+
else
|
160
|
+
# This type was already added
|
161
|
+
end
|
162
|
+
elsif type.is_a?(Class) && type < GraphQL::Schema::Directive
|
163
|
+
@directives << type
|
164
|
+
type.arguments.each do |name, arg|
|
165
|
+
arg_type = arg.type.unwrap
|
166
|
+
references_to(arg_type, from: arg)
|
167
|
+
add_type(arg_type, owner: arg, late_types: late_types, path: path + [name])
|
168
|
+
if arg.default_value?
|
169
|
+
@arguments_with_default_values << arg
|
170
|
+
end
|
171
|
+
end
|
172
|
+
else
|
173
|
+
@types[type.graphql_name] = type
|
174
|
+
add_directives_from(type)
|
175
|
+
if type.kind.fields?
|
176
|
+
type.fields.each do |name, field|
|
177
|
+
field_type = field.type.unwrap
|
178
|
+
references_to(field_type, from: field)
|
179
|
+
field_path = path + [name]
|
180
|
+
add_type(field_type, owner: field, late_types: late_types, path: field_path)
|
181
|
+
add_directives_from(field)
|
182
|
+
field.arguments.each do |arg_name, arg|
|
183
|
+
add_directives_from(arg)
|
184
|
+
arg_type = arg.type.unwrap
|
185
|
+
references_to(arg_type, from: arg)
|
186
|
+
add_type(arg_type, owner: arg, late_types: late_types, path: field_path + [arg_name])
|
187
|
+
if arg.default_value?
|
188
|
+
@arguments_with_default_values << arg
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
if type.kind.input_object?
|
194
|
+
type.arguments.each do |arg_name, arg|
|
195
|
+
add_directives_from(arg)
|
196
|
+
arg_type = arg.type.unwrap
|
197
|
+
references_to(arg_type, from: arg)
|
198
|
+
add_type(arg_type, owner: arg, late_types: late_types, path: path + [arg_name])
|
199
|
+
if arg.default_value?
|
200
|
+
@arguments_with_default_values << arg
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
if type.kind.union?
|
205
|
+
@possible_types[type.graphql_name] = type.possible_types
|
206
|
+
type.possible_types.each do |t|
|
207
|
+
add_type(t, owner: type, late_types: late_types, path: path + ["possible_types"])
|
208
|
+
end
|
209
|
+
end
|
210
|
+
if type.kind.interface?
|
211
|
+
type.orphan_types.each do |t|
|
212
|
+
add_type(t, owner: type, late_types: late_types, path: path + ["orphan_types"])
|
213
|
+
end
|
214
|
+
end
|
215
|
+
if type.kind.object?
|
216
|
+
@possible_types[type.graphql_name] = [type]
|
217
|
+
type.interface_type_memberships.each do |interface_type_membership|
|
218
|
+
case interface_type_membership
|
219
|
+
when Schema::TypeMembership
|
220
|
+
interface_type = interface_type_membership.abstract_type
|
221
|
+
# We can get these now; we'll have to get late-bound types later
|
222
|
+
if interface_type.is_a?(Module)
|
223
|
+
implementers = @possible_types[interface_type.graphql_name] ||= []
|
224
|
+
implementers << type
|
225
|
+
end
|
226
|
+
when String, Schema::LateBoundType
|
227
|
+
interface_type = interface_type_membership
|
228
|
+
else
|
229
|
+
raise ArgumentError, "Invariant: unexpected type membership for #{type.graphql_name}: #{interface_type_membership.class} (#{interface_type_membership.inspect})"
|
230
|
+
end
|
231
|
+
add_type(interface_type, owner: type, late_types: late_types, path: path + ["implements"])
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|