graphql-stitching 1.2.2 → 1.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +8 -2
- data/README.md +7 -66
- data/docs/federation_entities.md +70 -0
- data/gemfiles/graphql_1.13.9.gemfile +1 -1
- data/gemfiles/graphql_2.0.0.gemfile +6 -0
- data/gemfiles/graphql_2.1.0.gemfile +6 -0
- data/gemfiles/graphql_2.2.0.gemfile +6 -0
- data/lib/graphql/stitching/composer.rb +2 -1
- data/lib/graphql/stitching/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 99acc247a0e5e227236b0261b3f975e7277f642a9d76daaf4f6a985bfc4825ea
|
4
|
+
data.tar.gz: ef5f01132498ca4ba1be6f8593f189645ddf8fb6b6d8ab71f9b7d0e55d6ec682
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d1bd0db4c7f6d363231330222006f2bbc552a669227a38aeb7861dde843b59bc3e61b0f301f97d4a5c6b55193d01424cd9f240c0ff7a7ee483e49150686ac3da
|
7
|
+
data.tar.gz: 348aa663608fd8b0e5544ccf7ec500d4295a63bb9bd19a91031f927165da2a206024ce6cb17111c3ebda2c172e08072be8d01716c11f0a05c3ea8a9a4b99466e
|
data/.github/workflows/ci.yml
CHANGED
@@ -16,10 +16,16 @@ jobs:
|
|
16
16
|
ruby: 3.2
|
17
17
|
- gemfile: Gemfile
|
18
18
|
ruby: 3.1
|
19
|
-
- gemfile: gemfiles/graphql_1.13.9.gemfile
|
20
|
-
ruby: 3.1
|
21
19
|
- gemfile: Gemfile
|
22
20
|
ruby: 2.7
|
21
|
+
- gemfile: gemfiles/graphql_2.2.0.gemfile
|
22
|
+
ruby: 3.1
|
23
|
+
- gemfile: gemfiles/graphql_2.1.0.gemfile
|
24
|
+
ruby: 3.1
|
25
|
+
- gemfile: gemfiles/graphql_2.0.0.gemfile
|
26
|
+
ruby: 3.1
|
27
|
+
- gemfile: gemfiles/graphql_1.13.9.gemfile
|
28
|
+
ruby: 3.1
|
23
29
|
|
24
30
|
steps:
|
25
31
|
- uses: actions/checkout@v2
|
data/README.md
CHANGED
@@ -9,14 +9,13 @@ GraphQL stitching composes a single schema from multiple underlying GraphQL reso
|
|
9
9
|
- Multiple keys per merged type.
|
10
10
|
- Shared objects, fields, enums, and inputs across locations.
|
11
11
|
- Combining local and remote schemas.
|
12
|
-
- Type merging via arbitrary queries or federation `_entities` protocol.
|
13
12
|
- File uploads via [multipart form spec](https://github.com/jaydenseric/graphql-multipart-request-spec).
|
14
13
|
|
15
14
|
**NOT Supported:**
|
16
15
|
- Computed fields (ie: federation-style `@requires`).
|
17
16
|
- Subscriptions, defer/stream.
|
18
17
|
|
19
|
-
This Ruby implementation is a sibling to [GraphQL Tools](https://the-guild.dev/graphql/stitching) (JS) and [Bramble](https://movio.github.io/bramble/) (Go), and its capabilities fall somewhere in between them. GraphQL stitching is similar in concept to [Apollo Federation](https://www.apollographql.com/docs/federation/), though more generic.
|
18
|
+
This Ruby implementation is a sibling to [GraphQL Tools](https://the-guild.dev/graphql/stitching) (JS) and [Bramble](https://movio.github.io/bramble/) (Go), and its capabilities fall somewhere in between them. GraphQL stitching is similar in concept to [Apollo Federation](https://www.apollographql.com/docs/federation/), though more generic. The opportunity here is for a Ruby application to stitch its local schemas together or onto remote sources without requiring an additional proxy service running in another language. If your goal is to build a purely high-throughput API gateway, consider not using Ruby.
|
20
19
|
|
21
20
|
## Getting started
|
22
21
|
|
@@ -34,7 +33,7 @@ require "graphql/stitching"
|
|
34
33
|
|
35
34
|
## Usage
|
36
35
|
|
37
|
-
The quickest way to start is to use the provided [`Client`](./docs/client.md) component that wraps a stitched graph in an executable workflow with
|
36
|
+
The quickest way to start is to use the provided [`Client`](./docs/client.md) component that wraps a stitched graph in an executable workflow (with optional query plan caching hooks):
|
38
37
|
|
39
38
|
```ruby
|
40
39
|
movies_schema = <<~GRAPHQL
|
@@ -72,7 +71,7 @@ result = client.execute(
|
|
72
71
|
)
|
73
72
|
```
|
74
73
|
|
75
|
-
Schemas provided in [location settings](./docs/composer.md#performing-composition) may be class-based schemas with local resolvers (locally-executable schemas), or schemas built from SDL strings (schema definition language parsed using `GraphQL::Schema.from_definition`) and mapped to remote locations
|
74
|
+
Schemas provided in [location settings](./docs/composer.md#performing-composition) may be class-based schemas with local resolvers (locally-executable schemas), or schemas built from SDL strings (schema definition language parsed using `GraphQL::Schema.from_definition`) and mapped to remote locations via [executables](#executables).
|
76
75
|
|
77
76
|
While the `Client` constructor is an easy quick start, the library also has several discrete components that can be assembled into custom workflows:
|
78
77
|
|
@@ -87,11 +86,11 @@ While the `Client` constructor is an easy quick start, the library also has seve
|
|
87
86
|
|
88
87
|
![Merging types](./docs/images/merging.png)
|
89
88
|
|
90
|
-
To facilitate this merging of types, stitching must know how to cross-reference and fetch each variant of a type from its source location
|
89
|
+
To facilitate this merging of types, stitching must know how to cross-reference and fetch each variant of a type from its source location using [resolver queries](#merged-type-resolver-queries). For those in an Apollo ecosystem, there's also _limited_ support for merging types though a [federation `_entities` protocol](./docs/federation_entities.md).
|
91
90
|
|
92
|
-
### Merged
|
91
|
+
### Merged type resolver queries
|
93
92
|
|
94
|
-
Types
|
93
|
+
Types merge through resolver queries identified by a `@stitch` directive:
|
95
94
|
|
96
95
|
```graphql
|
97
96
|
directive @stitch(key: String!) repeatable on FIELD_DEFINITION
|
@@ -299,65 +298,6 @@ The library is configured to use a `@stitch` directive by default. You may custo
|
|
299
298
|
GraphQL::Stitching.stitch_directive = "merge"
|
300
299
|
```
|
301
300
|
|
302
|
-
### Merged types via Federation entities
|
303
|
-
|
304
|
-
The [Apollo Federation specification](https://www.apollographql.com/docs/federation/subgraph-spec/) defines a standard interface for accessing merged type variants across locations. Stitching can utilize a _subset_ of this interface to facilitate basic type merging. The following spec is supported:
|
305
|
-
|
306
|
-
- `@key(fields: "id")` (repeatable) specifies a key field for an object type. The key `fields` argument may only contain one field selection.
|
307
|
-
- `_Entity` is a union type that must contain all types that implement a `@key`.
|
308
|
-
- `_Any` is a scalar that recieves raw JSON objects; each object representation contains a `__typename` and the type's key field.
|
309
|
-
- `_entities(representations: [_Any!]!): [_Entity]!` is a root query for local entity types.
|
310
|
-
|
311
|
-
The composer will automatcially detect and stitch schemas with an `_entities` query, for example:
|
312
|
-
|
313
|
-
```ruby
|
314
|
-
products_schema = <<~GRAPHQL
|
315
|
-
directive @key(fields: String!) repeatable on OBJECT
|
316
|
-
|
317
|
-
type Product @key(fields: "id") {
|
318
|
-
id: ID!
|
319
|
-
name: String!
|
320
|
-
}
|
321
|
-
|
322
|
-
union _Entity = Product
|
323
|
-
scalar _Any
|
324
|
-
|
325
|
-
type Query {
|
326
|
-
user(id: ID!): User
|
327
|
-
_entities(representations: [_Any!]!): [_Entity]!
|
328
|
-
}
|
329
|
-
GRAPHQL
|
330
|
-
|
331
|
-
catalog_schema = <<~GRAPHQL
|
332
|
-
directive @key(fields: String!) repeatable on OBJECT
|
333
|
-
|
334
|
-
type Product @key(fields: "id") {
|
335
|
-
id: ID!
|
336
|
-
price: Float!
|
337
|
-
}
|
338
|
-
|
339
|
-
union _Entity = Product
|
340
|
-
scalar _Any
|
341
|
-
|
342
|
-
type Query {
|
343
|
-
_entities(representations: [_Any!]!): [_Entity]!
|
344
|
-
}
|
345
|
-
GRAPHQL
|
346
|
-
|
347
|
-
client = GraphQL::Stitching::Client.new(locations: {
|
348
|
-
products: {
|
349
|
-
schema: GraphQL::Schema.from_definition(products_schema),
|
350
|
-
executable: ...,
|
351
|
-
},
|
352
|
-
catalog: {
|
353
|
-
schema: GraphQL::Schema.from_definition(catalog_schema),
|
354
|
-
executable: ...,
|
355
|
-
},
|
356
|
-
})
|
357
|
-
```
|
358
|
-
|
359
|
-
It's perfectly fine to mix and match schemas that implement an `_entities` query with schemas that implement `@stitch` directives; the protocols achieve the same result. Note that stitching is much simpler than Apollo Federation by design, and that Federation's advanced routing features (such as the `@requires` and `@external` directives) will not work with stitching.
|
360
|
-
|
361
301
|
## Executables
|
362
302
|
|
363
303
|
An executable resource performs location-specific GraphQL requests. Executables may be `GraphQL::Schema` classes, or any object that responds to `.call(request, source, variables)` and returns a raw GraphQL response:
|
@@ -427,6 +367,7 @@ The [Executor](./docs/executor.md) component builds atop the Ruby fiber-based im
|
|
427
367
|
|
428
368
|
- [Modeling foreign keys for stitching](./docs/mechanics.md##modeling-foreign-keys-for-stitching)
|
429
369
|
- [Deploying a stitched schema](./docs/mechanics.md#deploying-a-stitched-schema)
|
370
|
+
- [Schema composition merge patterns](./docs/composer.md#merge-patterns)
|
430
371
|
- [Field selection routing](./docs/mechanics.md#field-selection-routing)
|
431
372
|
- [Root selection routing](./docs/mechanics.md#root-selection-routing)
|
432
373
|
- [Stitched errors](./docs/mechanics.md#stitched-errors)
|
@@ -0,0 +1,70 @@
|
|
1
|
+
## Merged types via Apollo Federation `_entities`
|
2
|
+
|
3
|
+
The [Apollo Federation specification](https://www.apollographql.com/docs/federation/subgraph-spec/) defines a standard interface for accessing merged type variants across locations. Stitching can utilize a _subset_ of this interface to facilitate basic type merging; the full spec is NOT supported and therefore is not fully interchangable with an Apollo Gateway.
|
4
|
+
|
5
|
+
To avoid confusion, using [basic resolver queries](../README.md#merged-type-resolver-queries) is recommended unless you specifically need to interact with a service built for an Apollo ecosystem. Even then, be wary that it does not exceed the supported spec by [using features that will not work](#federation-features-that-will-most-definitly-break).
|
6
|
+
|
7
|
+
### Supported spec
|
8
|
+
|
9
|
+
The following subset of the federation spec is supported:
|
10
|
+
|
11
|
+
- `@key(fields: "id")` (repeatable) specifies a key field for an object type. The key `fields` argument may only contain one field selection.
|
12
|
+
- `_Entity` is a union type that must contain all types that implement a `@key`.
|
13
|
+
- `_Any` is a scalar that recieves raw JSON objects; each object representation contains a `__typename` and the type's key field.
|
14
|
+
- `_entities(representations: [_Any!]!): [_Entity]!` is a root query for local entity types.
|
15
|
+
|
16
|
+
The composer will automatcially detect and stitch schemas with an `_entities` query, for example:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
products_schema = <<~GRAPHQL
|
20
|
+
directive @key(fields: String!) repeatable on OBJECT
|
21
|
+
|
22
|
+
type Product @key(fields: "id") {
|
23
|
+
id: ID!
|
24
|
+
name: String!
|
25
|
+
}
|
26
|
+
|
27
|
+
union _Entity = Product
|
28
|
+
scalar _Any
|
29
|
+
|
30
|
+
type Query {
|
31
|
+
user(id: ID!): User
|
32
|
+
_entities(representations: [_Any!]!): [_Entity]!
|
33
|
+
}
|
34
|
+
GRAPHQL
|
35
|
+
|
36
|
+
catalog_schema = <<~GRAPHQL
|
37
|
+
directive @key(fields: String!) repeatable on OBJECT
|
38
|
+
|
39
|
+
type Product @key(fields: "id") {
|
40
|
+
id: ID!
|
41
|
+
price: Float!
|
42
|
+
}
|
43
|
+
|
44
|
+
union _Entity = Product
|
45
|
+
scalar _Any
|
46
|
+
|
47
|
+
type Query {
|
48
|
+
_entities(representations: [_Any!]!): [_Entity]!
|
49
|
+
}
|
50
|
+
GRAPHQL
|
51
|
+
|
52
|
+
client = GraphQL::Stitching::Client.new(locations: {
|
53
|
+
products: {
|
54
|
+
schema: GraphQL::Schema.from_definition(products_schema),
|
55
|
+
executable: ...,
|
56
|
+
},
|
57
|
+
catalog: {
|
58
|
+
schema: GraphQL::Schema.from_definition(catalog_schema),
|
59
|
+
executable: ...,
|
60
|
+
},
|
61
|
+
})
|
62
|
+
```
|
63
|
+
|
64
|
+
It's perfectly fine to mix and match schemas that implement an `_entities` query with schemas that implement `@stitch` directives; the protocols achieve the same result.
|
65
|
+
|
66
|
+
### Federation features that will most definitly break
|
67
|
+
|
68
|
+
- `@external` fields will confuse the stitching query planner.
|
69
|
+
- `@requires` fields will not be sent any dependencies.
|
70
|
+
- No support for Apollo composition directives.
|
@@ -145,7 +145,8 @@ module GraphQL
|
|
145
145
|
|
146
146
|
builder = self
|
147
147
|
schema = Class.new(GraphQL::Schema) do
|
148
|
-
|
148
|
+
add_type_and_traverse(schema_types.values, root: false)
|
149
|
+
orphan_types(schema_types.values.select { |t| t.respond_to?(:kind) && t.kind.object? })
|
149
150
|
query schema_types[builder.query_name]
|
150
151
|
mutation schema_types[builder.mutation_name]
|
151
152
|
directives builder.schema_directives.values
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphql-stitching
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Greg MacWilliam
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-04-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: graphql
|
@@ -82,6 +82,7 @@ files:
|
|
82
82
|
- docs/README.md
|
83
83
|
- docs/client.md
|
84
84
|
- docs/composer.md
|
85
|
+
- docs/federation_entities.md
|
85
86
|
- docs/http_executable.md
|
86
87
|
- docs/images/library.png
|
87
88
|
- docs/images/merging.png
|
@@ -104,6 +105,9 @@ files:
|
|
104
105
|
- examples/merged_types/remote1.rb
|
105
106
|
- examples/merged_types/remote2.rb
|
106
107
|
- gemfiles/graphql_1.13.9.gemfile
|
108
|
+
- gemfiles/graphql_2.0.0.gemfile
|
109
|
+
- gemfiles/graphql_2.1.0.gemfile
|
110
|
+
- gemfiles/graphql_2.2.0.gemfile
|
107
111
|
- graphql-stitching.gemspec
|
108
112
|
- lib/graphql/stitching.rb
|
109
113
|
- lib/graphql/stitching/boundary.rb
|