Class: GraphitiGraphQL::Federation::SchemaDecorator
- Inherits:
-
Object
- Object
- GraphitiGraphQL::Federation::SchemaDecorator
- Defined in:
- lib/graphiti_graphql/federation/schema_decorator.rb
Class Method Summary collapse
Instance Method Summary collapse
- #add_federated_resource_interface(federated_resource) ⇒ Object
- #add_federated_resource_type(klass_name, interface: nil) ⇒ Object
- #add_federated_resources ⇒ Object
-
#add_resolve_reference ⇒ Object
Add to all local resource types This is if a remote federated resource belongs_to a local resource.
- #decorate ⇒ Object
- #define_connection_type(name, type_class) ⇒ Object
- #define_federated_belongs_to(federated_resource, relationship) ⇒ Object
- #define_federated_has_many(type_class, relationship) ⇒ Object
- #define_polymorphic_federated_resource_interface(klass_name) ⇒ Object
-
#each_federated_resource ⇒ Object
NB: test already registered bc 2 things have same relationship.
- #federated_resources ⇒ Object
-
#initialize(schema) ⇒ SchemaDecorator
constructor
A new instance of SchemaDecorator.
- #type_registry ⇒ Object
Constructor Details
#initialize(schema) ⇒ SchemaDecorator
Returns a new instance of SchemaDecorator.
8 9 10 |
# File 'lib/graphiti_graphql/federation/schema_decorator.rb', line 8 def initialize(schema) @schema = schema end |
Class Method Details
.decorate(schema) ⇒ Object
4 5 6 |
# File 'lib/graphiti_graphql/federation/schema_decorator.rb', line 4 def self.decorate(schema) new(schema).decorate end |
Instance Method Details
#add_federated_resource_interface(federated_resource) ⇒ Object
79 80 81 82 83 84 85 |
# File 'lib/graphiti_graphql/federation/schema_decorator.rb', line 79 def add_federated_resource_interface(federated_resource) interface = define_polymorphic_federated_resource_interface(federated_resource.klass_name) federated_resource.type_name.values.each do |name| add_federated_resource_type(name, interface: interface) end interface end |
#add_federated_resource_type(klass_name, interface: nil) ⇒ Object
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/graphiti_graphql/federation/schema_decorator.rb', line 96 def add_federated_resource_type(klass_name, interface: nil) federated_type = Class.new(@schema.class.base_object) federated_type.graphql_name klass_name federated_type.key(fields: "id") federated_type.extend_type federated_type.implements(interface) if interface federated_type.field :id, String, null: false, external: true federated_type.class_eval do def self.resolve_reference(reference, _context, _lookup) reference end end # NB must be registered before processing relationships type_registry[klass_name] = {type: federated_type} federated_type end |
#add_federated_resources ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/graphiti_graphql/federation/schema_decorator.rb', line 51 def add_federated_resources each_federated_resource do |type_class, federated_resource| federated_resource.relationships.each_pair do |name, relationship| if relationship.has_many? define_federated_has_many(type_class, relationship) elsif relationship.belongs_to? define_federated_belongs_to(federated_resource, relationship) end end end end |
#add_resolve_reference ⇒ Object
Add to all local resource types This is if a remote federated resource belongs_to a local resource
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/graphiti_graphql/federation/schema_decorator.rb', line 22 def add_resolve_reference @schema.type_registry.each_pair do |name, config| if config[:resource] local_type = config[:type] local_type.key(fields: "id") if local_type.respond_to?(:key) local_resource = Graphiti.resources .find { |r| r.name == config[:resource] } # TODO: maybe turn off the graphiti debug for these? local_type.define_singleton_method :resolve_reference do |reference, context, lookahead| Federation::Loaders::BelongsTo .for(local_resource, lookahead.selections.map(&:name)) .load(reference[:id]) end end end end |
#decorate ⇒ Object
12 13 14 15 16 17 18 |
# File 'lib/graphiti_graphql/federation/schema_decorator.rb', line 12 def decorate @schema.schema.send(:include, ApolloFederation::Schema) # NB if we add mutation support, make sure this is applied after @schema.schema.use(GraphQL::Batch) add_resolve_reference add_federated_resources end |
#define_connection_type(name, type_class) ⇒ Object
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/graphiti_graphql/federation/schema_decorator.rb', line 113 def define_connection_type(name, type_class) name = "#{name}FederatedConnection" if (registered = type_registry[name]) return registered[:type] end klass = Class.new(@schema.class.base_object) klass.graphql_name(name) klass.field :nodes, [type_class], null: false, extras: [:lookahead] @schema.send :register, name, klass klass end |
#define_federated_belongs_to(federated_resource, relationship) ⇒ Object
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/graphiti_graphql/federation/schema_decorator.rb', line 169 def define_federated_belongs_to(federated_resource, relationship) type_name = GraphitiSchema::Resource.gql_name(relationship.local_resource_class.name) local_type = type_registry[type_name][:type] # Todo maybe better way here interface = type_registry["I#{type_name}"] local_type = interface[:type] if interface local_types = [local_type] if interface local_types |= interface[:implementers] end local_types.each do |local| local.field relationship.name, type_registry[federated_resource.klass_name][:type], null: true end end |
#define_federated_has_many(type_class, relationship) ⇒ Object
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 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/graphiti_graphql/federation/schema_decorator.rb', line 129 def define_federated_has_many(type_class, relationship) local_name = GraphitiGraphQL::GraphitiSchema::Resource .gql_name(relationship.local_resource_class.name) local_type = type_registry[local_name][:type] local_resource_name = type_registry[local_name][:resource] local_resource = Graphiti.resources.find { |r| r.name == local_resource_name } local_interface = type_registry["I#{local_name}"] best_type = local_interface ? local_interface[:type] : local_type connection_type = define_connection_type(local_name, best_type) field = type_class.field relationship.name, connection_type, null: false, connection: false @schema.send :define_arguments_for_sideload_field, field, @schema.graphiti_schema.get_resource(local_resource_name) type_class.define_method relationship.name do |**arguments| {data: object, arguments: arguments} end connection_type.define_method :nodes do |lookahead:, **arguments| params = object[:arguments].as_json .deep_transform_keys { |key| key.to_s.underscore.to_sym } selections = lookahead.selections.map(&:name) selections << relationship.foreign_key selections << :_type # polymorphism params[:fields] = {local_resource.type => selections.join(",")} if (sort = Util.parse_sort(params[:sort])) params[:sort] = sort end Federation::Loaders::HasMany .for(relationship, params) .load(object[:data][:id]) end end |
#define_polymorphic_federated_resource_interface(klass_name) ⇒ Object
87 88 89 90 91 92 93 94 |
# File 'lib/graphiti_graphql/federation/schema_decorator.rb', line 87 def define_polymorphic_federated_resource_interface(klass_name) interface = Module.new interface.send(:include, @schema.class.base_interface) interface.graphql_name(klass_name) interface.field :id, String, null: false, external: true type_registry[klass_name] = {type: interface, interface: true} interface end |
#each_federated_resource ⇒ Object
NB: test already registered bc 2 things have same relationship
64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/graphiti_graphql/federation/schema_decorator.rb', line 64 def each_federated_resource federated_resources.each do |federated_resource| pre_registered = !!type_registry[federated_resource.type_name] type_class = if pre_registered type_registry[federated_resource.type_name][:type] elsif federated_resource.polymorphic? add_federated_resource_interface(federated_resource) else add_federated_resource_type(federated_resource.klass_name) end yield type_class, federated_resource end end |
#federated_resources ⇒ Object
39 40 41 42 43 44 45 |
# File 'lib/graphiti_graphql/federation/schema_decorator.rb', line 39 def federated_resources federated = [] Graphiti.resources.each do |r| federated |= (r.config[:federated_resources] || []) end federated end |
#type_registry ⇒ Object
47 48 49 |
# File 'lib/graphiti_graphql/federation/schema_decorator.rb', line 47 def type_registry @schema.type_registry end |