apollo-federation 2.2.4 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ba95ea6ff91193e1c977c0bd3eea9a5e9d697ae8f1fdf189823eb81d0a911bc3
4
- data.tar.gz: 51e4f2204aaab9ce67b3578454ec2d33b59ed9ffb90e73331a36b93e19b73dd9
3
+ metadata.gz: fe0ae888b83a68558821badedaaacc8c2e175dbf1aff918f347ec7ca797d8c0a
4
+ data.tar.gz: ceae483d68658009536a64de692473cebad87d0810027c7c80219df52b7d8cfc
5
5
  SHA512:
6
- metadata.gz: 94cb699aa812877a646ded92f8fc1a4b12e8137410fea54c470e851e402110b8bb6b2c4ab1c42bb422e09616a910da90683e38ea69bf85365f3a86e9121aa3cc
7
- data.tar.gz: a74321947eb59666acd5420df26c554d48166f1f29aeaa4d3ce30d6e4f374090c7c7c83c4585c8fdbbad585adec8de6421f90c68072d0d144e33c73a6fa37bf4
6
+ metadata.gz: d3aaba325f9d53ceef358dc287963afe2374ca75d9a6cd3e2b988c9e008e47496238b81eb59c538d4bbb2693a967a52ce72c8efb8c643321480692b3b7666d6c
7
+ data.tar.gz: 8ed45a0a43cf239ddbb6dbdd8f4375f209efec48f5d9f17282b83b564e9d98c6b41bab51bbaf622b57265ed2d1a93bacacf9e71da54b1205b07c9a3fa762f56a
data/CHANGELOG.md CHANGED
@@ -1,3 +1,29 @@
1
+ # [3.2.0](https://github.com/Gusto/apollo-federation-ruby/compare/v3.1.0...v3.2.0) (2022-08-15)
2
+
3
+
4
+ ### Features
5
+
6
+ * allow custom namespace for linked directives ([03fdfea](https://github.com/Gusto/apollo-federation-ruby/commit/03fdfeafaaea3c98ca4b7a734ce760ea08410530))
7
+
8
+ # [3.1.0](https://github.com/Gusto/apollo-federation-ruby/compare/v3.0.0...v3.1.0) (2022-06-21)
9
+
10
+
11
+ ### Features
12
+
13
+ * Support Federation v2 ([#196](https://github.com/Gusto/apollo-federation-ruby/issues/196)) ([238736c](https://github.com/Gusto/apollo-federation-ruby/commit/238736cdb6f12121ce2a295c7a28fba3990012b9)), closes [/www.apollographql.com/docs/federation/federation-2/moving-to-federation-2/#opt-in-to-federation-2](https://github.com//www.apollographql.com/docs/federation/federation-2/moving-to-federation-2//issues/opt-in-to-federation-2)
14
+
15
+ # [3.0.0](https://github.com/Gusto/apollo-federation-ruby/compare/v2.2.4...v3.0.0) (2022-04-05)
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * camelize string fields to match sym behavior ([8f0382b](https://github.com/Gusto/apollo-federation-ruby/commit/8f0382b346d2cde5be252138275d67373b36acd7))
21
+
22
+
23
+ ### BREAKING CHANGES
24
+
25
+ * string fields will be camelized by default rather than passed as is.
26
+
1
27
  ## [2.2.4](https://github.com/Gusto/apollo-federation-ruby/compare/v2.2.3...v2.2.4) (2022-04-01)
2
28
 
3
29
 
data/README.md CHANGED
@@ -61,6 +61,15 @@ class MySchema < GraphQL::Schema
61
61
  end
62
62
  ```
63
63
 
64
+ **Optional:** To opt in to Federation v2, specify the version in your schema:
65
+
66
+ ```ruby
67
+ class MySchema < GraphQL::Schema
68
+ include ApolloFederation::Schema
69
+ federation version: '2.0'
70
+ end
71
+ ```
72
+
64
73
  ## Example
65
74
 
66
75
  The [`example`](./example/) folder contains a Ruby implementation of Apollo's [`federation-demo`](https://github.com/apollographql/federation-demo). To run it locally, install the Ruby dependencies:
@@ -160,6 +169,59 @@ end
160
169
  ```
161
170
  See [field set syntax](#field-set-syntax) for more details on the format of the `fields` option.
162
171
 
172
+ ### The `@shareable` directive (Apollo Federation v2)
173
+
174
+ [Apollo documentation](https://www.apollographql.com/docs/federation/federated-types/federated-directives/#shareable)
175
+
176
+ Call `shareable` within your class definition:
177
+
178
+ ```ruby
179
+ class User < BaseObject
180
+ shareable
181
+ end
182
+ ```
183
+
184
+ Pass the `shareable: true` option to your field definition:
185
+
186
+ ```ruby
187
+ class User < BaseObject
188
+ field :id, ID, null: false, shareable: true
189
+ end
190
+ ```
191
+
192
+ ### The `@inaccessible` directive (Apollo Federation v2)
193
+
194
+ [Apollo documentation](https://www.apollographql.com/docs/federation/federated-types/federated-directives/#inaccessible)
195
+
196
+ Call `inaccessible` within your class definition:
197
+
198
+ ```ruby
199
+ class User < BaseObject
200
+ inaccessible
201
+ end
202
+ ```
203
+
204
+ Pass the `inaccessible: true` option to your field definition:
205
+
206
+ ```ruby
207
+ class User < BaseObject
208
+ field :id, ID, null: false, inaccessible: true
209
+ end
210
+ ```
211
+
212
+ ### The `@override` directive (Apollo Federation v2)
213
+
214
+ [Apollo documentation](https://www.apollographql.com/docs/federation/federated-types/federated-directives/#override)
215
+
216
+ Pass the `override:` option to your field definition:
217
+
218
+ ```ruby
219
+ class Product < BaseObject
220
+ field :id, ID, null: false
221
+ field :inStock, Boolean, null: false, override: { from: 'Products' }
222
+ end
223
+ ```
224
+
163
225
  ### Field set syntax
164
226
 
165
227
  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:
@@ -55,20 +55,28 @@ module ApolloFederation
55
55
 
56
56
  def merge_directives(node, type)
57
57
  if type.is_a?(ApolloFederation::HasDirectives)
58
- directives = type.federation_directives
58
+ directives = type.federation_directives || []
59
59
  else
60
60
  directives = []
61
61
  end
62
62
 
63
- (directives || []).each do |directive|
63
+ directives.each do |directive|
64
64
  node = node.merge_directive(
65
- name: directive[:name],
65
+ name: directive_name(directive),
66
66
  arguments: build_arguments_node(directive[:arguments]),
67
67
  )
68
68
  end
69
69
  node
70
70
  end
71
71
 
72
+ def directive_name(directive)
73
+ if schema.federation_2?
74
+ "#{schema.link_namespace}__#{directive[:name]}"
75
+ else
76
+ directive[:name]
77
+ end
78
+ end
79
+
72
80
  def build_arguments_node(arguments)
73
81
  (arguments || []).map do |arg|
74
82
  GraphQL::Language::Nodes::Argument.new(name: arg[:name], value: arg[:values])
@@ -7,31 +7,78 @@ module ApolloFederation
7
7
  module Field
8
8
  include HasDirectives
9
9
 
10
- def initialize(*args, external: false, requires: nil, provides: nil, **kwargs, &block)
10
+ VERSION_1_DIRECTIVES = %i[external requires provides].freeze
11
+ VERSION_2_DIRECTIVES = %i[shareable inaccessible override].freeze
12
+
13
+ def initialize(*args, **kwargs, &block)
14
+ add_v1_directives(**kwargs)
15
+ add_v2_directives(**kwargs)
16
+
17
+ # Remove the custom kwargs
18
+ kwargs = kwargs.delete_if do |k, _|
19
+ VERSION_1_DIRECTIVES.include?(k) || VERSION_2_DIRECTIVES.include?(k)
20
+ end
21
+
22
+ # Pass on the default args:
23
+ super(*args, **kwargs, &block)
24
+ end
25
+
26
+ private
27
+
28
+ def add_v1_directives(external: nil, requires: nil, provides: nil, **_kwargs)
11
29
  if external
12
30
  add_directive(name: 'external')
13
31
  end
32
+
14
33
  if requires
15
34
  add_directive(
16
35
  name: 'requires',
17
36
  arguments: [
18
37
  name: 'fields',
19
- values: ApolloFederation::FieldSetSerializer.serialize(requires[:fields]),
38
+ values: ApolloFederation::FieldSetSerializer.serialize(
39
+ requires[:fields],
40
+ camelize: requires.fetch(:camelize, true),
41
+ ),
20
42
  ],
21
43
  )
22
44
  end
45
+
23
46
  if provides
24
47
  add_directive(
25
48
  name: 'provides',
26
49
  arguments: [
27
50
  name: 'fields',
28
- values: ApolloFederation::FieldSetSerializer.serialize(provides[:fields]),
51
+ values: ApolloFederation::FieldSetSerializer.serialize(
52
+ provides[:fields],
53
+ camelize: provides.fetch(:camelize, true),
54
+ ),
29
55
  ],
30
56
  )
31
57
  end
32
58
 
33
- # Pass on the default args:
34
- super(*args, **kwargs, &block)
59
+ nil
60
+ end
61
+
62
+ def add_v2_directives(shareable: nil, inaccessible: nil, override: nil, **_kwargs)
63
+ if shareable
64
+ add_directive(name: 'shareable')
65
+ end
66
+
67
+ if inaccessible
68
+ add_directive(name: 'inaccessible')
69
+ end
70
+
71
+ if override
72
+ add_directive(
73
+ name: 'override',
74
+ arguments: [
75
+ name: 'from',
76
+ values: override[:from],
77
+ ],
78
+ )
79
+ end
80
+
81
+ nil
35
82
  end
36
83
  end
37
84
  end
@@ -6,20 +6,18 @@ module ApolloFederation
6
6
  module FieldSetSerializer
7
7
  extend self
8
8
 
9
- def serialize(fields)
9
+ def serialize(fields, camelize: true)
10
10
  case fields
11
11
  when Hash
12
12
  fields.map do |field, nested_selections|
13
- "#{camelize(field)} { #{serialize(nested_selections)} }"
13
+ "#{camelize(field, camelize)} { #{serialize(nested_selections, camelize: camelize)} }"
14
14
  end.join(' ')
15
15
  when Array
16
16
  fields.map do |field|
17
- serialize(field)
17
+ serialize(field, camelize: camelize)
18
18
  end.join(' ')
19
- when String
20
- fields
21
- when Symbol
22
- camelize(fields)
19
+ when Symbol, String
20
+ camelize(fields, camelize)
23
21
  else
24
22
  raise ArgumentError, "Unexpected field set type: #{fields.class}"
25
23
  end
@@ -27,8 +25,8 @@ module ApolloFederation
27
25
 
28
26
  private
29
27
 
30
- def camelize(field)
31
- GraphQL::Schema::Member::BuildType.camelize(field.to_s)
28
+ def camelize(field, camelize)
29
+ camelize ? GraphQL::Schema::Member::BuildType.camelize(field.to_s) : field.to_s
32
30
  end
33
31
  end
34
32
  end
@@ -18,12 +18,16 @@ module ApolloFederation
18
18
  add_directive(name: 'extends')
19
19
  end
20
20
 
21
- def key(fields:)
21
+ def inaccessible
22
+ add_directive(name: 'inaccessible')
23
+ end
24
+
25
+ def key(fields:, camelize: true)
22
26
  add_directive(
23
27
  name: 'key',
24
28
  arguments: [
25
29
  name: 'fields',
26
- values: ApolloFederation::FieldSetSerializer.serialize(fields),
30
+ values: ApolloFederation::FieldSetSerializer.serialize(fields, camelize: camelize),
27
31
  ],
28
32
  )
29
33
  end
@@ -16,12 +16,20 @@ module ApolloFederation
16
16
  add_directive(name: 'extends')
17
17
  end
18
18
 
19
- def key(fields:)
19
+ def shareable
20
+ add_directive(name: 'shareable')
21
+ end
22
+
23
+ def inaccessible
24
+ add_directive(name: 'inaccessible')
25
+ end
26
+
27
+ def key(fields:, camelize: true)
20
28
  add_directive(
21
29
  name: 'key',
22
30
  arguments: [
23
31
  name: 'fields',
24
- values: ApolloFederation::FieldSetSerializer.serialize(fields),
32
+ values: ApolloFederation::FieldSetSerializer.serialize(fields, camelize: camelize),
25
33
  ],
26
34
  )
27
35
  end
@@ -12,9 +12,35 @@ module ApolloFederation
12
12
  end
13
13
 
14
14
  module CommonMethods
15
+ FEDERATION_2_PREFIX = <<~SCHEMA
16
+ extend schema
17
+ @link(url: "https://specs.apollo.dev/federation/v2.0")
18
+
19
+ SCHEMA
20
+
21
+ def federation(version: '1.0', link: {})
22
+ @federation_version = version
23
+ @link = { as: 'federation' }.merge(link)
24
+ end
25
+
26
+ def federation_version
27
+ @federation_version || '1.0'
28
+ end
29
+
30
+ def federation_2?
31
+ Gem::Version.new(federation_version.to_s) >= Gem::Version.new('2.0.0')
32
+ end
33
+
15
34
  def federation_sdl(context: nil)
16
35
  document_from_schema = FederatedDocumentFromSchemaDefinition.new(self, context: context)
17
- GraphQL::Language::Printer.new.print(document_from_schema.document)
36
+
37
+ output = GraphQL::Language::Printer.new.print(document_from_schema.document)
38
+ output.prepend(FEDERATION_2_PREFIX) if federation_2?
39
+ output
40
+ end
41
+
42
+ def link_namespace
43
+ @link[:as]
18
44
  end
19
45
 
20
46
  def query(new_query_object = nil)
@@ -34,6 +60,14 @@ module ApolloFederation
34
60
 
35
61
  private
36
62
 
63
+ def federation_2_prefix
64
+ <<~SCHEMA
65
+ extend schema
66
+ @link(url: "https://specs.apollo.dev/federation/v2.0", as: "#{link_namespace}")
67
+
68
+ SCHEMA
69
+ end
70
+
37
71
  def schema_entities
38
72
  # Create a temporary schema that inherits from this one to extract the types
39
73
  types_schema = Class.new(self)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ApolloFederation
4
- VERSION = '2.2.4'
4
+ VERSION = '3.2.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: apollo-federation
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.4
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Noa Elad
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-04-01 00:00:00.000000000 Z
12
+ date: 2022-08-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: graphql