graphql-stitching 1.4.0 → 1.4.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 448ca61527e02c6f232fa811e7e99ba1aa243bc58685f313ca5613a6724ea306
4
- data.tar.gz: a0af76ea7eb429d60f5a7e4df4c39103539a01a69136c769f027cef52a108cab
3
+ metadata.gz: b81b29cdab4287ba09d6081595b83b4edcc96f0921790483f44d53ff946fb441
4
+ data.tar.gz: 39c3351dbb4a712aa4f43006017660a961a2056b82b96a5a14b3110b1ecfad44
5
5
  SHA512:
6
- metadata.gz: 8cea8a8674d67a421059e32778ffc3d1bbd699fa307efe2aead4571925ed77d8da7852431ef99c5809e0106ff16af212c26a6372c211b2d287d3a2c4cef5eb80
7
- data.tar.gz: 972f74c60afef0c615d8dc6a3069bb7ddfbe88a84e22a8940d496037ab67f23491c639e8cc3e145b98697c921eb6c20577babec4be2a8e6a3221264e925cdc01
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!) repeatable on FIELD_DEFINITION
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!) repeatable on FIELD_DEFINITION
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 `key`, or `__typename`. This syntax allows sending multiple arguments that intermix stitching keys with complex input shapes and other static values:
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: String="database"): [Entity]!
243
- @stitch(key: "id", arguments: "keys: { id: $.id, type: $.__typename }, source: 'cache'")
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].each_key do |location|
59
- if resolver_keys.none? { _1.locations.include?(location) }
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.default_argument_name]
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.default_argument_name}"
568
+ "#{argument.graphql_name}: $.#{key.primitive_name}"
569
569
  end
570
570
 
571
571
  arguments = Resolver.parse_arguments_with_field(arguments_format, subgraph_field)
@@ -244,6 +244,7 @@ module GraphQL
244
244
  fragment = @request.fragment_definitions[node.name]
245
245
  next unless @supergraph.locations_by_type[fragment.type.name].include?(current_location)
246
246
 
247
+ requires_typename = true
247
248
  fragment_type = @supergraph.memoized_schema_types[fragment.type.name]
248
249
  is_same_scope = fragment_type == parent_type
249
250
  selection_set = is_same_scope ? locale_selections : []
@@ -251,7 +252,6 @@ module GraphQL
251
252
 
252
253
  unless is_same_scope
253
254
  locale_selections << GraphQL::Language::Nodes::InlineFragment.new(type: fragment.type, selections: selection_set)
254
- requires_typename = true
255
255
  end
256
256
 
257
257
  else
@@ -42,7 +42,7 @@ module GraphQL::Stitching
42
42
  to_definition == other.to_definition
43
43
  end
44
44
 
45
- def default_argument_name
45
+ def primitive_name
46
46
  length == 1 ? first.name : nil
47
47
  end
48
48
 
@@ -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
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module GraphQL
4
4
  module Stitching
5
- VERSION = "1.4.0"
5
+ VERSION = "1.4.2"
6
6
  end
7
7
  end
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.4.0
4
+ version: 1.4.2
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-07-02 00:00:00.000000000 Z
11
+ date: 2024-07-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: graphql