apollo-federation 1.1.5 → 2.0.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 +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +107 -18
- data/lib/apollo-federation/schema.rb +24 -52
- data/lib/apollo-federation/version.rb +1 -1
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9ec8b363ade4047069cbbf7774e3fc88b93c4e9b61ae8ca0e5baf60e6ca0f488
|
4
|
+
data.tar.gz: 73866b38229feea6644ed23ce2ac9adad4cf9c2fb760f4426e519ec317afc256
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 03d6d4e2dcc6243ca7e05c40225b0b3c8516d777ef2c9ba37516ab0fde3dd8a0c61e7872526be323a47e7c1ce908fe490547bb66ad300985e04dbd047879fa5e
|
7
|
+
data.tar.gz: 924c9aae3668493d09559173a7d073aaf751fffad84df0958a6de9e4e4bfcebd984e4ba77cb5e06d8a1add6760271c075574f46c91e5f7c38f68bdb274f4e1be
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
# [2.0.0](https://github.com/Gusto/apollo-federation-ruby/compare/v1.1.5...v2.0.0) (2022-01-27)
|
2
|
+
|
3
|
+
|
4
|
+
* Remove beta disclaimer (#165) ([29da3de](https://github.com/Gusto/apollo-federation-ruby/commit/29da3deb0163c38d5d08f084e5e8dc67d8454358)), closes [#165](https://github.com/Gusto/apollo-federation-ruby/issues/165)
|
5
|
+
|
6
|
+
|
7
|
+
### BREAKING CHANGES
|
8
|
+
|
9
|
+
* GraphQL 1.9.x support removed
|
10
|
+
|
1
11
|
## [1.1.5](https://github.com/Gusto/apollo-federation-ruby/compare/v1.1.4...v1.1.5) (2020-10-29)
|
2
12
|
|
3
13
|
|
data/README.md
CHANGED
@@ -1,13 +1,9 @@
|
|
1
1
|
# apollo-federation
|
2
2
|
|
3
|
-
[](https://circleci.com/gh/Gusto/apollo-federation-ruby/tree/main)
|
4
4
|
|
5
5
|
This gem extends the [GraphQL Ruby](http://graphql-ruby.org/) gem to add support for creating an [Apollo Federation](https://www.apollographql.com/docs/apollo-server/federation/introduction/) schema.
|
6
6
|
|
7
|
-
## DISCLAIMER
|
8
|
-
|
9
|
-
This gem is still in a beta stage and may have some bugs or incompatibilities. See the [Known Issues and Limitations](#known-issues-and-limitations) below. If you run into any problems, please [file an issue](https://github.com/Gusto/apollo-federation-ruby/issues).
|
10
|
-
|
11
7
|
## Installation
|
12
8
|
|
13
9
|
Add this line to your application's Gemfile:
|
@@ -85,12 +81,12 @@ Start the gateway:
|
|
85
81
|
|
86
82
|
This will start up the gateway and serve it at http://localhost:5000.
|
87
83
|
|
88
|
-
|
89
84
|
## Usage
|
90
85
|
|
91
86
|
The API is designed to mimic the API of [Apollo's federation library](https://www.apollographql.com/docs/apollo-server/federation/introduction/). It's best to read and understand the way federation works, in general, before attempting to use this library.
|
92
87
|
|
93
88
|
### Extending a type
|
89
|
+
|
94
90
|
[Apollo documentation](https://www.apollographql.com/docs/apollo-server/federation/core-concepts/#extending-external-types)
|
95
91
|
|
96
92
|
Call `extend_type` within your class definition:
|
@@ -102,6 +98,7 @@ end
|
|
102
98
|
```
|
103
99
|
|
104
100
|
### The `@key` directive
|
101
|
+
|
105
102
|
[Apollo documentation](https://www.apollographql.com/docs/apollo-server/federation/core-concepts/#entities-and-keys)
|
106
103
|
|
107
104
|
Call `key` within your class definition:
|
@@ -113,6 +110,7 @@ end
|
|
113
110
|
```
|
114
111
|
|
115
112
|
### The `@external` directive
|
113
|
+
|
116
114
|
[Apollo documentation](https://www.apollographql.com/docs/apollo-server/federation/core-concepts/#referencing-external-types)
|
117
115
|
|
118
116
|
Pass the `external: true` option to your field definition:
|
@@ -124,6 +122,7 @@ end
|
|
124
122
|
```
|
125
123
|
|
126
124
|
### The `@requires` directive
|
125
|
+
|
127
126
|
[Apollo documentation](https://www.apollographql.com/docs/apollo-server/federation/advanced-features/#computed-fields)
|
128
127
|
|
129
128
|
Pass the `requires:` option to your field definition:
|
@@ -137,6 +136,7 @@ end
|
|
137
136
|
```
|
138
137
|
|
139
138
|
### The `@provides` directive
|
139
|
+
|
140
140
|
[Apollo documentation](https://www.apollographql.com/docs/apollo-server/federation/advanced-features/#using-denormalized-data)
|
141
141
|
|
142
142
|
Pass the `provides:` option to your field definition:
|
@@ -148,6 +148,7 @@ end
|
|
148
148
|
```
|
149
149
|
|
150
150
|
### Reference resolvers
|
151
|
+
|
151
152
|
[Apollo documentation](https://www.apollographql.com/docs/apollo-server/api/apollo-federation/#__resolvereference)
|
152
153
|
|
153
154
|
Define a `resolve_reference` class method on your object. The method will be passed the reference from another service and the context for the query.
|
@@ -166,20 +167,108 @@ To support [federated tracing](https://www.apollographql.com/docs/apollo-server/
|
|
166
167
|
|
167
168
|
1. Add `use ApolloFederation::Tracing` to your schema class.
|
168
169
|
2. Change your controller to add `tracing_enabled: true` to the execution context based on the presence of the "include trace" header:
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
170
|
+
```ruby
|
171
|
+
def execute
|
172
|
+
# ...
|
173
|
+
context = {
|
174
|
+
tracing_enabled: ApolloFederation::Tracing.should_add_traces(headers)
|
175
|
+
}
|
176
|
+
# ...
|
177
|
+
end
|
178
|
+
```
|
179
|
+
|
180
|
+
## Exporting the Federated SDL
|
181
|
+
|
182
|
+
When using tools like [rover](https://www.apollographql.com/docs/rover/) for schema validation, etc., add a Rake task that prints the Federated SDL to a file:
|
183
|
+
|
184
|
+
```rb
|
185
|
+
namespace :graphql do
|
186
|
+
namespace :federation do
|
187
|
+
task :dump do
|
188
|
+
File.write("schema.graphql", MySchema.federation_sdl)
|
176
189
|
end
|
177
|
-
|
190
|
+
end
|
191
|
+
end
|
192
|
+
```
|
193
|
+
|
194
|
+
Example validation check with Rover and Apollo Studio:
|
195
|
+
|
196
|
+
```sh
|
197
|
+
bin/rake graphql:federation:dump
|
198
|
+
rover subgraph check mygraph@current --name mysubgraph --schema schema.graphql
|
199
|
+
```
|
200
|
+
|
201
|
+
## Testing the federated schema
|
202
|
+
|
203
|
+
This library does not include any testing helpers currently. A federated service receives subgraph queries from the Apollo Gateway via the `_entities` field and that can be tested in a request spec.
|
204
|
+
|
205
|
+
With Apollo Gateway setup to hit your service locally or by using existing query logs, you can retrieve the generated `_entities` queries.
|
206
|
+
|
207
|
+
For example, if you have a blog service that exposes posts by a given author, the query received by the service might look like this.
|
208
|
+
|
209
|
+
```graphql
|
210
|
+
query($representations: [_Any!]!) {
|
211
|
+
_entities(representations: $representations) {
|
212
|
+
... on BlogPost {
|
213
|
+
id
|
214
|
+
title
|
215
|
+
body
|
216
|
+
}
|
217
|
+
}
|
218
|
+
}
|
219
|
+
```
|
220
|
+
|
221
|
+
Where `$representations` is an array of entity references from the gateway.
|
222
|
+
|
223
|
+
```JSON
|
224
|
+
{
|
225
|
+
"representations": [
|
226
|
+
{
|
227
|
+
"__typename": "BlogPost",
|
228
|
+
"id": 1
|
229
|
+
},
|
230
|
+
{
|
231
|
+
"__typename": "BlogPost",
|
232
|
+
"id": 2
|
233
|
+
}
|
234
|
+
]
|
235
|
+
}
|
236
|
+
```
|
237
|
+
|
238
|
+
Using RSpec as an example, a request spec for this query.
|
239
|
+
|
240
|
+
```ruby
|
241
|
+
it "resolves the blog post entities" do
|
242
|
+
blog_post = BlogPost.create!(attributes)
|
243
|
+
|
244
|
+
query = <<~GRAPHQL
|
245
|
+
query($representations: [_Any!]!) {
|
246
|
+
_entities(representations: $representations) {
|
247
|
+
... on BlogPost {
|
248
|
+
id
|
249
|
+
title
|
250
|
+
body
|
251
|
+
}
|
252
|
+
}
|
253
|
+
}
|
254
|
+
GRAPHQL
|
255
|
+
|
256
|
+
variables = { representations: [{ __typename: "BlogPost", id: blog_post.id }] }
|
257
|
+
|
258
|
+
result = Schema.execute(query, variables: variables)
|
259
|
+
|
260
|
+
expect(result.dig("data", "_entities", 0, "id")).to eq(blog_post.id)
|
261
|
+
end
|
262
|
+
```
|
263
|
+
|
264
|
+
See discussion at [#74](https://github.com/Gusto/apollo-federation-ruby/issues/74) and an [internal spec that resolves \_entities](https://github.com/Gusto/apollo-federation-ruby/blob/1d3baf4f8efcd02e7bf5bc7e3fee5b4fb963cd25/spec/apollo-federation/entities_field_spec.rb#L164) for more details.
|
178
265
|
|
179
266
|
## Known Issues and Limitations
|
180
|
-
|
181
|
-
|
267
|
+
|
268
|
+
- Only works with class-based schemas, the legacy `.define` API will not be supported
|
269
|
+
- Does not add directives to the output of `Schema.to_definition`. Since `graphql-ruby` doesn't natively support schema directives, the directives will only be visible to the [Apollo Gateway](https://www.apollographql.com/docs/apollo-server/api/apollo-gateway/) through the `Query._service` field (see the [Apollo Federation specification](https://www.apollographql.com/docs/apollo-server/federation/federation-spec/)) or via [`Schema#federation_sdl`](https://github.com/Gusto/apollo-federation-ruby/blob/1d3baf4f8efcd02e7bf5bc7e3fee5b4fb963cd25/lib/apollo-federation/schema.rb#L19) as explained above.
|
182
270
|
|
183
271
|
## Maintainers
|
184
|
-
|
185
|
-
|
272
|
+
|
273
|
+
- [Rylan Collins](https://github.com/rylanc)
|
274
|
+
- [Noa Elad](https://github.com/noaelad)
|
@@ -8,11 +8,7 @@ require 'apollo-federation/federated_document_from_schema_definition.rb'
|
|
8
8
|
module ApolloFederation
|
9
9
|
module Schema
|
10
10
|
def self.included(klass)
|
11
|
-
|
12
|
-
klass.extend(OneTenMethods)
|
13
|
-
else
|
14
|
-
klass.extend(OneNineMethods)
|
15
|
-
end
|
11
|
+
klass.extend(CommonMethods)
|
16
12
|
end
|
17
13
|
|
18
14
|
module CommonMethods
|
@@ -21,53 +17,6 @@ module ApolloFederation
|
|
21
17
|
GraphQL::Language::Printer.new.print(document_from_schema.document)
|
22
18
|
end
|
23
19
|
|
24
|
-
private
|
25
|
-
|
26
|
-
def federation_query(query_obj)
|
27
|
-
# Build the new query object with the '_service' field
|
28
|
-
if query_obj.nil?
|
29
|
-
base = GraphQL::Schema::Object
|
30
|
-
elsif Gem::Version.new(GraphQL::VERSION) >= Gem::Version.new('1.10.0')
|
31
|
-
base = query_obj
|
32
|
-
else
|
33
|
-
base = query_obj.metadata[:type_class]
|
34
|
-
end
|
35
|
-
|
36
|
-
klass = Class.new(base) do
|
37
|
-
# TODO: Maybe the name should inherit from the original Query name
|
38
|
-
# Or MAYBE we should just modify the original class?
|
39
|
-
graphql_name 'Query'
|
40
|
-
|
41
|
-
include EntitiesField
|
42
|
-
include ServiceField
|
43
|
-
end
|
44
|
-
|
45
|
-
klass.define_service_field
|
46
|
-
klass
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
# TODO: Remove these once we drop support for graphql 1.9
|
51
|
-
module OneNineMethods
|
52
|
-
include CommonMethods
|
53
|
-
|
54
|
-
def to_graphql
|
55
|
-
orig_defn = super
|
56
|
-
@query_object = federation_query(query)
|
57
|
-
|
58
|
-
possible_entities = orig_defn.types.values.select do |type|
|
59
|
-
!type.introspection? && !type.default_scalar? && type.is_a?(GraphQL::ObjectType) &&
|
60
|
-
type.metadata[:federation_directives]&.any? { |directive| directive[:name] == 'key' }
|
61
|
-
end
|
62
|
-
@query_object.define_entities_field(possible_entities)
|
63
|
-
|
64
|
-
super
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
module OneTenMethods
|
69
|
-
include CommonMethods
|
70
|
-
|
71
20
|
def query(new_query_object = nil)
|
72
21
|
if new_query_object
|
73
22
|
@orig_query_object = new_query_object
|
@@ -100,6 +49,29 @@ module ApolloFederation
|
|
100
49
|
type.federation_directives&.any? { |directive| directive[:name] == 'key' }
|
101
50
|
end
|
102
51
|
end
|
52
|
+
|
53
|
+
def federation_query(query_obj)
|
54
|
+
# Build the new query object with the '_service' field
|
55
|
+
if query_obj.nil?
|
56
|
+
base = GraphQL::Schema::Object
|
57
|
+
elsif Gem::Version.new(GraphQL::VERSION) >= Gem::Version.new('1.10.0')
|
58
|
+
base = query_obj
|
59
|
+
else
|
60
|
+
base = query_obj.metadata[:type_class]
|
61
|
+
end
|
62
|
+
|
63
|
+
klass = Class.new(base) do
|
64
|
+
# TODO: Maybe the name should inherit from the original Query name
|
65
|
+
# Or MAYBE we should just modify the original class?
|
66
|
+
graphql_name 'Query'
|
67
|
+
|
68
|
+
include EntitiesField
|
69
|
+
include ServiceField
|
70
|
+
end
|
71
|
+
|
72
|
+
klass.define_service_field
|
73
|
+
klass
|
74
|
+
end
|
103
75
|
end
|
104
76
|
end
|
105
77
|
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:
|
4
|
+
version: 2.0.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:
|
12
|
+
date: 2022-01-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: graphql
|
@@ -17,28 +17,28 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - ">="
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: 1.
|
20
|
+
version: 1.10.14
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - ">="
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: 1.
|
27
|
+
version: 1.10.14
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: google-protobuf
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
32
|
- - "~>"
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version:
|
34
|
+
version: 3.13.0
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
39
|
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version:
|
41
|
+
version: 3.13.0
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: actionpack
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -234,7 +234,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
234
234
|
- !ruby/object:Gem::Version
|
235
235
|
version: '0'
|
236
236
|
requirements: []
|
237
|
-
rubygems_version: 3.0.3
|
237
|
+
rubygems_version: 3.0.3.1
|
238
238
|
signing_key:
|
239
239
|
specification_version: 4
|
240
240
|
summary: A Ruby implementation of Apollo Federation
|