Skip to content

Commit

Permalink
feat: Support Interfaces (#27)
Browse files Browse the repository at this point in the history
* Support interfaces

* Touch up README

* Add tests

* Clean up

* Better test name

* Adjust API

* Lint
  • Loading branch information
rtymchyk authored and rylanc committed Oct 22, 2019
1 parent df1761d commit 33d0097
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 2 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,17 @@ class BaseObject < GraphQL::Schema::Object
end
```

Include the `ApolloFederation::Interface` module in your base interface module:

```ruby
module BaseInterface
include GraphQL::Schema::Interface
include ApolloFederation::Interface

field_class BaseField
end
```

Finally, include the `ApolloFederation::Schema` module in your schema:

```ruby
Expand Down
1 change: 1 addition & 0 deletions lib/apollo-federation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
require 'apollo-federation/version'
require 'apollo-federation/schema'
require 'apollo-federation/object'
require 'apollo-federation/interface'
require 'apollo-federation/field'
require 'apollo-federation/tracing/proto'
require 'apollo-federation/tracing/node_map'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ def build_object_type_node(object_type)
merge_directives(object_node, object_type.metadata[:federation_directives])
end

def build_interface_type_node(interface_type)
field_node = super
merge_directives(field_node, interface_type.metadata[:federation_directives])
end

def build_field_node(field_type)
field_node = super
merge_directives(field_node, field_type.metadata[:federation_directives])
Expand Down
31 changes: 31 additions & 0 deletions lib/apollo-federation/interface.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true

require 'apollo-federation/has_directives'

module ApolloFederation
module Interface
def self.included(klass)
klass.definition_methods do
include DefinitionMethods
end
end

module DefinitionMethods
include HasDirectives

def extend_type
add_directive(name: 'extends')
end

def key(fields:)
add_directive(
name: 'key',
arguments: [
name: 'fields',
values: fields,
],
)
end
end
end
end
1 change: 0 additions & 1 deletion lib/apollo-federation/object.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ def self.included(klass)
module ClassMethods
include HasDirectives

# TODO: We should support extending interfaces at some point
def extend_type
add_directive(name: 'extends')
end
Expand Down
2 changes: 1 addition & 1 deletion lib/apollo-federation/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def to_graphql
end

possible_entities = orig_defn.types.values.select do |type|
!type.introspection? && !type.default_scalar? &&
!type.introspection? && !type.default_scalar? && type.is_a?(GraphQL::ObjectType) &&
type.metadata[:federation_directives]&.any? { |directive| directive[:name] == 'key' }
end

Expand Down
59 changes: 59 additions & 0 deletions spec/apollo-federation/service_field_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
require 'apollo-federation/schema'
require 'apollo-federation/field'
require 'apollo-federation/object'
require 'apollo-federation/interface'

RSpec.describe ApolloFederation::ServiceField do
let(:base_schema) do
Expand Down Expand Up @@ -144,6 +145,64 @@ def execute_sdl(schema)
)
end

it 'returns valid SDL for interface types' do
base_interface = Module.new do
include GraphQL::Schema::Interface
include ApolloFederation::Interface

graphql_name 'Interface'
end

product = Module.new do
include base_interface

graphql_name 'Product'

key fields: :upc
field :upc, String, null: false
end

book = Class.new(base_object) do
implements product

graphql_name 'Book'

extend_type

key fields: :upc
field :upc, String, null: false, external: true
end

pen = Class.new(base_object) do
implements product

graphql_name 'Pen'

key fields: :upc
field :upc, String, null: false
end

schema = Class.new(base_schema) do
orphan_types book, pen
end

expect(execute_sdl(schema)).to match_sdl(
<<~GRAPHQL,
type Book implements Product @extends @key(fields: "upc") {
upc: String! @external
}
type Pen implements Product @key(fields: "upc") {
upc: String!
}
interface Product @key(fields: "upc") {
upc: String!
}
GRAPHQL
)
end

context 'when a Query object is provided' do
it 'returns valid SDL for @key directives' do
product = Class.new(base_object) do
Expand Down

0 comments on commit 33d0097

Please sign in to comment.