|
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" |
@@ -1582,10 +1583,7 @@ def directives(*new_directives) |
1582 | 1583 | # @param new_directive [Class] |
1583 | 1584 | # @return void |
1584 | 1585 | def directive(new_directive) |
1585 | | - own_directives[new_directive.graphql_name] ||= begin |
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 @@ def query_stack_error(query, err) |
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 @@ def own_middleware |
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 commit comments