Skip to content

Commit 8c6e112

Browse files
dweinandgrxy
andauthored
feat: add tag directive from federation v2 (#210)
* Add tag directive from federation v2 * Add tag to union types * Add tag to enum and enum value * Fix style issues * Add tags to scalar * Support multiple tags per field * Add tag to input objects * Add tag support for arguments and input fields * Remove trailing line * fix: rubocop + tests * feat: ensure @tag is not namespaced --------- Co-authored-by: Grex <[email protected]> Co-authored-by: Grex <[email protected]>
1 parent 297fe79 commit 8c6e112

File tree

14 files changed

+840
-32
lines changed

14 files changed

+840
-32
lines changed

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,26 @@ class Product < BaseObject
222222
end
223223
```
224224

225+
### The `@tag` directive (Apollo Federation v2)
226+
227+
[Apollo documentation](https://www.apollographql.com/docs/federation/federated-types/federated-directives/#tag)
228+
229+
Call `tag` within your class definition:
230+
231+
```ruby
232+
class User < BaseObject
233+
tag name: 'private'
234+
end
235+
```
236+
237+
Pass the `tags:` option to your field definition:
238+
239+
```ruby
240+
class User < BaseObject
241+
field :id, ID, null: false, tags: [{ name: 'private' }]
242+
end
243+
```
244+
225245
### Field set syntax
226246

227247
Field sets can be either strings encoded with the Apollo Field Set [syntax]((https://www.apollographql.com/docs/apollo-server/federation/federation-spec/#scalar-_fieldset)) or arrays, hashes and snake case symbols that follow the graphql-ruby conventions:

lib/apollo-federation.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@
44
require 'apollo-federation/schema'
55
require 'apollo-federation/object'
66
require 'apollo-federation/interface'
7+
require 'apollo-federation/union'
8+
require 'apollo-federation/enum'
9+
require 'apollo-federation/enum_value'
710
require 'apollo-federation/field'
11+
require 'apollo-federation/scalar'
12+
require 'apollo-federation/input_object'
13+
require 'apollo-federation/argument'
814
require 'apollo-federation/tracing/proto'
915
require 'apollo-federation/tracing/node_map'
1016
require 'apollo-federation/tracing/tracer'

lib/apollo-federation/argument.rb

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# frozen_string_literal: true
2+
3+
require 'apollo-federation/has_directives'
4+
5+
module ApolloFederation
6+
module Argument
7+
include HasDirectives
8+
9+
VERSION_2_DIRECTIVES = %i[tags].freeze
10+
11+
def initialize(*args, **kwargs, &block)
12+
add_v2_directives(**kwargs)
13+
14+
# Remove the custom kwargs
15+
kwargs = kwargs.delete_if do |k, _|
16+
VERSION_2_DIRECTIVES.include?(k)
17+
end
18+
19+
# Pass on the default args:
20+
super(*args, **kwargs, &block)
21+
end
22+
23+
private
24+
25+
def add_v2_directives(tags: [], **_kwargs)
26+
tags.each do |tag|
27+
add_directive(
28+
name: 'tag',
29+
arguments: [
30+
name: 'name',
31+
values: tag[:name],
32+
],
33+
)
34+
end
35+
end
36+
end
37+
end

lib/apollo-federation/enum.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# frozen_string_literal: true
2+
3+
require 'apollo-federation/has_directives'
4+
5+
module ApolloFederation
6+
module Enum
7+
def self.included(klass)
8+
klass.extend(ClassMethods)
9+
end
10+
11+
module ClassMethods
12+
include HasDirectives
13+
14+
def tag(name:)
15+
add_directive(name: 'tag', arguments: [name: 'name', values: name])
16+
end
17+
end
18+
end
19+
end
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# frozen_string_literal: true
2+
3+
require 'apollo-federation/has_directives'
4+
5+
module ApolloFederation
6+
module EnumValue
7+
include HasDirectives
8+
9+
VERSION_2_DIRECTIVES = %i[tags].freeze
10+
11+
def initialize(*args, **kwargs, &block)
12+
add_v2_directives(**kwargs)
13+
14+
# Remove the custom kwargs
15+
kwargs = kwargs.delete_if do |k, _|
16+
VERSION_2_DIRECTIVES.include?(k)
17+
end
18+
19+
# Pass on the default args:
20+
super(*args, **kwargs, &block)
21+
end
22+
23+
private
24+
25+
def add_v2_directives(tags: [], **_kwargs)
26+
tags.each do |tag|
27+
add_directive(
28+
name: 'tag',
29+
arguments: [
30+
name: 'name',
31+
values: tag[:name],
32+
],
33+
)
34+
end
35+
end
36+
end
37+
end

lib/apollo-federation/federated_document_from_schema_definition.rb

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ class FederatedDocumentFromSchemaDefinition < GraphQL::Language::DocumentFromSch
1414
'_entities',
1515
'_service',
1616
].freeze
17-
INACCESSIBLE_DIRECTIVE = 'inaccessible'
1817

1918
def build_object_type_node(object_type)
2019
object_node = super
@@ -28,8 +27,38 @@ def build_object_type_node(object_type)
2827
end
2928

3029
def build_interface_type_node(interface_type)
31-
field_node = super
32-
merge_directives(field_node, interface_type)
30+
interface_node = super
31+
merge_directives(interface_node, interface_type)
32+
end
33+
34+
def build_union_type_node(union_type)
35+
union_node = super
36+
merge_directives(union_node, union_type)
37+
end
38+
39+
def build_enum_type_node(enum_type)
40+
enum_node = super
41+
merge_directives(enum_node, enum_type)
42+
end
43+
44+
def build_enum_value_node(enum_value_type)
45+
enum_value_node = super
46+
merge_directives(enum_value_node, enum_value_type)
47+
end
48+
49+
def build_scalar_type_node(scalar_type)
50+
scalar_node = super
51+
merge_directives(scalar_node, scalar_type)
52+
end
53+
54+
def build_input_object_node(input_object_type)
55+
input_object_node = super
56+
merge_directives(input_object_node, input_object_type)
57+
end
58+
59+
def build_argument_node(argument_type)
60+
argument_node = super
61+
merge_directives(argument_node, argument_type)
3362
end
3463

3564
def build_field_node(field_type)
@@ -71,7 +100,7 @@ def merge_directives(node, type)
71100
end
72101

73102
def directive_name(directive)
74-
if schema.federation_2? && directive[:name] != INACCESSIBLE_DIRECTIVE
103+
if schema.federation_2? && !Schema::IMPORTED_DIRECTIVES.include?(directive[:name])
75104
"#{schema.link_namespace}__#{directive[:name]}"
76105
else
77106
directive[:name]

lib/apollo-federation/field.rb

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module Field
88
include HasDirectives
99

1010
VERSION_1_DIRECTIVES = %i[external requires provides].freeze
11-
VERSION_2_DIRECTIVES = %i[shareable inaccessible override].freeze
11+
VERSION_2_DIRECTIVES = %i[shareable inaccessible override tags].freeze
1212

1313
def initialize(*args, **kwargs, &block)
1414
add_v1_directives(**kwargs)
@@ -59,7 +59,7 @@ def add_v1_directives(external: nil, requires: nil, provides: nil, **_kwargs)
5959
nil
6060
end
6161

62-
def add_v2_directives(shareable: nil, inaccessible: nil, override: nil, **_kwargs)
62+
def add_v2_directives(shareable: nil, inaccessible: nil, override: nil, tags: [], **_kwargs)
6363
if shareable
6464
add_directive(name: 'shareable')
6565
end
@@ -78,6 +78,16 @@ def add_v2_directives(shareable: nil, inaccessible: nil, override: nil, **_kwarg
7878
)
7979
end
8080

81+
tags.each do |tag|
82+
add_directive(
83+
name: 'tag',
84+
arguments: [
85+
name: 'name',
86+
values: tag[:name],
87+
],
88+
)
89+
end
90+
8191
nil
8292
end
8393
end
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# frozen_string_literal: true
2+
3+
require 'apollo-federation/has_directives'
4+
5+
module ApolloFederation
6+
module InputObject
7+
def self.included(klass)
8+
klass.extend(ClassMethods)
9+
end
10+
11+
module ClassMethods
12+
include HasDirectives
13+
14+
def tag(name:)
15+
add_directive(name: 'tag', arguments: [name: 'name', values: name])
16+
end
17+
end
18+
end
19+
end

lib/apollo-federation/interface.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ def inaccessible
2222
add_directive(name: 'inaccessible')
2323
end
2424

25+
def tag(name:)
26+
add_directive(name: 'tag', arguments: [name: 'name', values: name])
27+
end
28+
2529
def key(fields:, camelize: true)
2630
add_directive(
2731
name: 'key',

lib/apollo-federation/object.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ def interface_object
2828
add_directive(name: 'interfaceObject')
2929
end
3030

31+
def tag(name:)
32+
add_directive(name: 'tag', arguments: [name: 'name', values: name])
33+
end
34+
3135
def key(fields:, camelize: true)
3236
add_directive(
3337
name: 'key',

0 commit comments

Comments
 (0)