graphql-stitching 1.2.2 → 1.2.3
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/.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
|

|
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
|