apollo-federation 1.1.5 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![CircleCI](https://circleci.com/gh/Gusto/apollo-federation-ruby/tree/
|
3
|
+
[![CircleCI](https://circleci.com/gh/Gusto/apollo-federation-ruby/tree/main.svg?style=svg)](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
|