graphql-stitching 1.4.1 → 1.4.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +12 -6
- data/docs/mechanics.md +2 -2
- data/lib/graphql/stitching/composer/validate_resolvers.rb +4 -2
- data/lib/graphql/stitching/composer.rb +2 -2
- data/lib/graphql/stitching/resolver/keys.rb +1 -1
- data/lib/graphql/stitching/supergraph.rb +5 -1
- data/lib/graphql/stitching/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b81b29cdab4287ba09d6081595b83b4edcc96f0921790483f44d53ff946fb441
|
4
|
+
data.tar.gz: 39c3351dbb4a712aa4f43006017660a961a2056b82b96a5a14b3110b1ecfad44
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d376c15fa17088797be0b2f7ab42a94cf24050f68b37640aac88cc13a526d56f0ee366290b246e4cc6838a60050b9d9073610366cb7ad5bdb0a9a3435e688dd4
|
7
|
+
data.tar.gz: 6a4fda5651bdd8794f59497e32bb9421c1d3f931a706483b55088597efdc9fe0bb1166dca16a66832c4ded42a21c89de2a7a8f2dc36cfb51bc44cfd40df9c4da
|
data/README.md
CHANGED
@@ -101,7 +101,7 @@ This directive (or [static configuration](#sdl-based-schemas)) is applied to roo
|
|
101
101
|
|
102
102
|
```ruby
|
103
103
|
products_schema = <<~GRAPHQL
|
104
|
-
directive @stitch(key: String
|
104
|
+
directive @stitch(key: String!, arguments: String) repeatable on FIELD_DEFINITION
|
105
105
|
|
106
106
|
type Product {
|
107
107
|
id: ID!
|
@@ -114,7 +114,7 @@ products_schema = <<~GRAPHQL
|
|
114
114
|
GRAPHQL
|
115
115
|
|
116
116
|
catalog_schema = <<~GRAPHQL
|
117
|
-
directive @stitch(key: String
|
117
|
+
directive @stitch(key: String!, arguments: String) repeatable on FIELD_DEFINITION
|
118
118
|
|
119
119
|
type Product {
|
120
120
|
id: ID!
|
@@ -226,7 +226,7 @@ type Query {
|
|
226
226
|
}
|
227
227
|
```
|
228
228
|
|
229
|
-
Key insertions are prefixed by `$` and specify a dot-notation path to any selections made by the resolver
|
229
|
+
Key insertions are prefixed by `$` and specify a dot-notation path to any selections made by the resolver key, or `__typename`. This syntax allows sending multiple arguments that intermix stitching keys with complex input shapes and other static values:
|
230
230
|
|
231
231
|
```graphql
|
232
232
|
type Product {
|
@@ -237,10 +237,14 @@ input EntityKey {
|
|
237
237
|
id: ID!
|
238
238
|
type: String!
|
239
239
|
}
|
240
|
+
enum EntitySource {
|
241
|
+
DATABASE
|
242
|
+
CACHE
|
243
|
+
}
|
240
244
|
|
241
245
|
type Query {
|
242
|
-
entities(keys: [EntityKey!]!, source:
|
243
|
-
@stitch(key: "id", arguments: "keys: { id: $.id, type: $.__typename }, source:
|
246
|
+
entities(keys: [EntityKey!]!, source: EntitySource = DATABASE): [Entity]!
|
247
|
+
@stitch(key: "id", arguments: "keys: { id: $.id, type: $.__typename }, source: CACHE")
|
244
248
|
}
|
245
249
|
```
|
246
250
|
|
@@ -265,6 +269,7 @@ input CustomFieldLookup {
|
|
265
269
|
ownerType: String!
|
266
270
|
key: String!
|
267
271
|
}
|
272
|
+
|
268
273
|
type Query {
|
269
274
|
customFields(lookups: [CustomFieldLookup!]!): [CustomField]! @stitch(
|
270
275
|
key: "owner { id type } key",
|
@@ -320,6 +325,7 @@ class StitchingResolver < GraphQL::Schema::Directive
|
|
320
325
|
locations FIELD_DEFINITION
|
321
326
|
repeatable true
|
322
327
|
argument :key, String, required: true
|
328
|
+
argument :arguments, String, required: false
|
323
329
|
end
|
324
330
|
|
325
331
|
class Query < GraphQL::Schema::Object
|
@@ -354,7 +360,7 @@ supergraph = GraphQL::Stitching::Composer.new.perform({
|
|
354
360
|
executable: ->() { ... },
|
355
361
|
stitch: [
|
356
362
|
{ field_name: "productById", key: "id" },
|
357
|
-
{ field_name: "productBySku", key: "sku" },
|
363
|
+
{ field_name: "productBySku", key: "sku", arguments: "mySku: $.sku" },
|
358
364
|
]
|
359
365
|
},
|
360
366
|
# ...
|
data/docs/mechanics.md
CHANGED
@@ -90,7 +90,7 @@ class GraphQlController
|
|
90
90
|
variables: params[:variables],
|
91
91
|
operation_name: params[:operation_name]
|
92
92
|
)
|
93
|
-
end
|
93
|
+
end
|
94
94
|
end
|
95
95
|
```
|
96
96
|
|
@@ -345,4 +345,4 @@ type Query {
|
|
345
345
|
}
|
346
346
|
```
|
347
347
|
|
348
|
-
In this graph, `Widget` is a merged type without a resolver query in location C. This works because all of its fields are resolvable in other locations; that means location C can provide outbound representations of this type without ever needing to resolve inbound requests for it. Outbound types do still require a shared key field (such as `id` above) that allow them to join with data in other resolver locations (such as `price` above).
|
348
|
+
In this graph, `Widget` is a merged type without a resolver query in location C. This works because all of its fields are resolvable in other locations; that means location C can provide outbound representations of this type without ever needing to resolve inbound requests for it. Outbound types do still require a shared key field (such as `id` above) that allow them to join with data in other resolver locations (such as `price` above). Support for this pattern is limited to single-field keys, [composite keys](../README.md#composite-type-keys) require a resolver definition.
|
@@ -55,8 +55,10 @@ module GraphQL::Stitching
|
|
55
55
|
end
|
56
56
|
|
57
57
|
# All locations of a merged type must include at least one resolver key
|
58
|
-
supergraph.fields_by_type_and_location[type.graphql_name].
|
59
|
-
|
58
|
+
supergraph.fields_by_type_and_location[type.graphql_name].each do |location, field_names|
|
59
|
+
has_resolver_key = resolver_keys.any? { _1.locations.include?(location) }
|
60
|
+
has_primitive_match = resolver_keys.any? { field_names.include?(_1.primitive_name) }
|
61
|
+
unless has_resolver_key || has_primitive_match
|
60
62
|
raise ValidationError, "A resolver key is required for `#{type.graphql_name}` in #{location} to join with other locations."
|
61
63
|
end
|
62
64
|
end
|
@@ -557,7 +557,7 @@ module GraphQL
|
|
557
557
|
argument = if subgraph_field.arguments.size == 1
|
558
558
|
subgraph_field.arguments.values.first
|
559
559
|
else
|
560
|
-
subgraph_field.arguments[key.
|
560
|
+
subgraph_field.arguments[key.primitive_name]
|
561
561
|
end
|
562
562
|
|
563
563
|
unless argument
|
@@ -565,7 +565,7 @@ module GraphQL
|
|
565
565
|
"An argument mapping is required for unmatched names and composite keys."
|
566
566
|
end
|
567
567
|
|
568
|
-
"#{argument.graphql_name}: $.#{key.
|
568
|
+
"#{argument.graphql_name}: $.#{key.primitive_name}"
|
569
569
|
end
|
570
570
|
|
571
571
|
arguments = Resolver.parse_arguments_with_field(arguments_format, subgraph_field)
|
@@ -147,7 +147,11 @@ module GraphQL
|
|
147
147
|
def possible_keys_for_type_and_location(type_name, location)
|
148
148
|
possible_keys_by_type = @possible_keys_by_type_and_location[type_name] ||= {}
|
149
149
|
possible_keys_by_type[location] ||= possible_keys_for_type(type_name).select do |key|
|
150
|
-
key.locations.include?(location)
|
150
|
+
next true if key.locations.include?(location)
|
151
|
+
|
152
|
+
# Outbound-only locations without resolver queries may dynamically match primitive keys
|
153
|
+
location_fields = fields_by_type_and_location[type_name][location] || GraphQL::Stitching::EMPTY_ARRAY
|
154
|
+
location_fields.include?(key.primitive_name)
|
151
155
|
end
|
152
156
|
end
|
153
157
|
|