graphql-stitching 1.0.4 → 1.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/docs/client.md +4 -4
- data/docs/composer.md +3 -0
- data/docs/executor.md +2 -2
- data/lib/graphql/stitching/client.rb +2 -2
- data/lib/graphql/stitching/composer.rb +25 -17
- data/lib/graphql/stitching/executor/boundary_source.rb +5 -4
- data/lib/graphql/stitching/{selection_hint.rb → export_selection.rb} +4 -4
- data/lib/graphql/stitching/planner.rb +10 -8
- data/lib/graphql/stitching/request.rb +18 -14
- data/lib/graphql/stitching/shaper.rb +3 -3
- data/lib/graphql/stitching/skip_include.rb +6 -2
- data/lib/graphql/stitching/version.rb +1 -1
- data/lib/graphql/stitching.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fbeabcd8c2327504cc5ccc613942d163bddddb2087e7eb90c966861777d67b9d
|
4
|
+
data.tar.gz: cf03589e91ef96fb8dc9b74ca2703c20095e586bab45f91a89b3579376edbdac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 78b5d6bbf4abccb99795c6225e1a61807ed74f94ad9ce5bdde0be534133e101c7d51f677d3c89aebaad7ebe2b125ff11a192a3d1a29cdacb3d3b51049801212f
|
7
|
+
data.tar.gz: ade024c4ace1474d9c7a7cd80fb8820fc71e456e566d89fe656d07bf4b64e60db83561546a908b5d2fcbec9d88ac740a7080946e981a74f7bd904b3da0aeebfb
|
data/docs/client.md
CHANGED
@@ -61,16 +61,16 @@ Arguments for the `execute` method include:
|
|
61
61
|
The client provides cache hooks to enable caching query plans across requests. Without caching, every request made to the client will be planned individually. With caching, a query may be planned once, cached, and then executed from cache for subsequent requests. Cache keys are a normalized digest of each query string.
|
62
62
|
|
63
63
|
```ruby
|
64
|
-
client.on_cache_read do |key, _context|
|
64
|
+
client.on_cache_read do |key, _context, _request|
|
65
65
|
$redis.get(key) # << 3P code
|
66
66
|
end
|
67
67
|
|
68
|
-
client.on_cache_write do |key, payload, _context|
|
68
|
+
client.on_cache_write do |key, payload, _context, _request|
|
69
69
|
$redis.set(key, payload) # << 3P code
|
70
70
|
end
|
71
71
|
```
|
72
72
|
|
73
|
-
Note that inlined input data works against caching, so you should _avoid_ this:
|
73
|
+
Note that inlined input data works against caching, so you should _avoid_ this when possible:
|
74
74
|
|
75
75
|
```graphql
|
76
76
|
query {
|
@@ -78,7 +78,7 @@ query {
|
|
78
78
|
}
|
79
79
|
```
|
80
80
|
|
81
|
-
Instead,
|
81
|
+
Instead, leverage query variables so that the document body remains consistent across requests:
|
82
82
|
|
83
83
|
```graphql
|
84
84
|
query($id: ID!) {
|
data/docs/composer.md
CHANGED
@@ -12,6 +12,7 @@ composer = GraphQL::Stitching::Composer.new(
|
|
12
12
|
mutation_name: "Mutation",
|
13
13
|
description_merger: ->(values_by_location, info) { values_by_location.values.join("\n") },
|
14
14
|
deprecation_merger: ->(values_by_location, info) { values_by_location.values.first },
|
15
|
+
default_value_merger: ->(values_by_location, info) { values_by_location.values.first },
|
15
16
|
directive_kwarg_merger: ->(values_by_location, info) { values_by_location.values.last },
|
16
17
|
root_field_location_selector: ->(locations, info) { locations.last },
|
17
18
|
)
|
@@ -27,6 +28,8 @@ Constructor arguments:
|
|
27
28
|
|
28
29
|
- **`deprecation_merger:`** _optional_, a [value merger function](#value-merger-functions) for merging element deprecation strings from across locations.
|
29
30
|
|
31
|
+
- **`default_value_merger:`** _optional_, a [value merger function](#value-merger-functions) for merging argument default values from across locations.
|
32
|
+
|
30
33
|
- **`directive_kwarg_merger:`** _optional_, a [value merger function](#value-merger-functions) for merging directive keyword arguments from across locations.
|
31
34
|
|
32
35
|
- **`root_field_location_selector:`** _optional_, selects a default routing location for root fields with multiple locations. Use this to prioritize sending root fields to their primary data sources (only applies while routing the root operation scope). This handler receives an array of possible locations and an info object with field information, and should return the prioritized location. The last location is used by default.
|
data/docs/executor.md
CHANGED
@@ -50,8 +50,8 @@ The raw result will contain many irregularities from the stitching process, howe
|
|
50
50
|
"data" => {
|
51
51
|
"product" => {
|
52
52
|
"upc" => "1",
|
53
|
-
"
|
54
|
-
"
|
53
|
+
"_export_upc" => "1",
|
54
|
+
"_export_typename" => "Product",
|
55
55
|
"name" => "iPhone",
|
56
56
|
"price" => nil,
|
57
57
|
}
|
@@ -75,14 +75,14 @@ module GraphQL
|
|
75
75
|
|
76
76
|
def fetch_plan(request)
|
77
77
|
if @on_cache_read
|
78
|
-
cached_plan = @on_cache_read.call(request.digest, request.context)
|
78
|
+
cached_plan = @on_cache_read.call(request.digest, request.context, request)
|
79
79
|
return GraphQL::Stitching::Plan.from_json(JSON.parse(cached_plan)) if cached_plan
|
80
80
|
end
|
81
81
|
|
82
82
|
plan = yield
|
83
83
|
|
84
84
|
if @on_cache_write
|
85
|
-
@on_cache_write.call(request.digest, JSON.generate(plan.as_json), request.context)
|
85
|
+
@on_cache_write.call(request.digest, JSON.generate(plan.as_json), request.context, request)
|
86
86
|
end
|
87
87
|
|
88
88
|
plan
|
@@ -5,9 +5,13 @@ module GraphQL
|
|
5
5
|
class Composer
|
6
6
|
class ComposerError < StitchingError; end
|
7
7
|
class ValidationError < ComposerError; end
|
8
|
+
class ReferenceType < GraphQL::Schema::Object
|
9
|
+
field(:f, String) do
|
10
|
+
argument(:a, String)
|
11
|
+
end
|
12
|
+
end
|
8
13
|
|
9
|
-
|
10
|
-
|
14
|
+
NO_DEFAULT_VALUE = ReferenceType.get_field("f").get_argument("a").default_value
|
11
15
|
BASIC_VALUE_MERGER = ->(values_by_location, _info) { values_by_location.values.find { !_1.nil? } }
|
12
16
|
BASIC_ROOT_FIELD_LOCATION_SELECTOR = ->(locations, _info) { locations.last }
|
13
17
|
|
@@ -16,6 +20,8 @@ module GraphQL
|
|
16
20
|
"ValidateBoundaries",
|
17
21
|
].freeze
|
18
22
|
|
23
|
+
attr_reader :query_name, :mutation_name, :candidate_types_by_name_and_location, :schema_directives
|
24
|
+
|
19
25
|
def initialize(
|
20
26
|
query_name: "Query",
|
21
27
|
mutation_name: "Mutation",
|
@@ -47,7 +53,7 @@ module GraphQL
|
|
47
53
|
end
|
48
54
|
end
|
49
55
|
|
50
|
-
# "
|
56
|
+
# "directive_name" => merged_directive
|
51
57
|
@schema_directives = @candidate_directives_by_name_and_location.each_with_object({}) do |(directive_name, directives_by_location), memo|
|
52
58
|
memo[directive_name] = build_directive(directive_name, directives_by_location)
|
53
59
|
end
|
@@ -82,19 +88,20 @@ module GraphQL
|
|
82
88
|
|
83
89
|
# "Typename" => merged_type
|
84
90
|
schema_types = @candidate_types_by_name_and_location.each_with_object({}) do |(type_name, types_by_location), memo|
|
85
|
-
kinds = types_by_location.values.map { _1.kind.name }.uniq
|
91
|
+
kinds = types_by_location.values.map { _1.kind.name }.tap(&:uniq!)
|
86
92
|
|
87
93
|
if kinds.length > 1
|
88
94
|
raise ComposerError, "Cannot merge different kinds for `#{type_name}`. Found: #{kinds.join(", ")}."
|
89
95
|
end
|
90
96
|
|
97
|
+
extract_boundaries(type_name, types_by_location) if type_name == @query_name
|
98
|
+
|
91
99
|
memo[type_name] = case kinds.first
|
92
100
|
when "SCALAR"
|
93
101
|
build_scalar_type(type_name, types_by_location)
|
94
102
|
when "ENUM"
|
95
103
|
build_enum_type(type_name, types_by_location, enum_usage)
|
96
104
|
when "OBJECT"
|
97
|
-
extract_boundaries(type_name, types_by_location) if type_name == @query_name
|
98
105
|
build_object_type(type_name, types_by_location)
|
99
106
|
when "INTERFACE"
|
100
107
|
build_interface_type(type_name, types_by_location)
|
@@ -194,8 +201,8 @@ module GraphQL
|
|
194
201
|
graphql_name(directive_name)
|
195
202
|
description(builder.merge_descriptions(directive_name, directives_by_location))
|
196
203
|
repeatable(directives_by_location.values.any?(&:repeatable?))
|
197
|
-
locations(*directives_by_location.values.flat_map(&:locations).uniq)
|
198
|
-
builder.build_merged_arguments(directive_name, directives_by_location, self)
|
204
|
+
locations(*directives_by_location.values.flat_map(&:locations).tap(&:uniq!))
|
205
|
+
builder.build_merged_arguments(directive_name, directives_by_location, self, directive_name: directive_name)
|
199
206
|
end
|
200
207
|
end
|
201
208
|
|
@@ -256,7 +263,7 @@ module GraphQL
|
|
256
263
|
description(builder.merge_descriptions(type_name, types_by_location))
|
257
264
|
|
258
265
|
interface_names = types_by_location.values.flat_map { _1.interfaces.map(&:graphql_name) }
|
259
|
-
interface_names.uniq.each do |interface_name|
|
266
|
+
interface_names.tap(&:uniq!).each do |interface_name|
|
260
267
|
implements(builder.build_type_binding(interface_name))
|
261
268
|
end
|
262
269
|
|
@@ -274,7 +281,7 @@ module GraphQL
|
|
274
281
|
description(builder.merge_descriptions(type_name, types_by_location))
|
275
282
|
|
276
283
|
interface_names = types_by_location.values.flat_map { _1.interfaces.map(&:graphql_name) }
|
277
|
-
interface_names.uniq.each do |interface_name|
|
284
|
+
interface_names.tap(&:uniq!).each do |interface_name|
|
278
285
|
implements(builder.build_type_binding(interface_name))
|
279
286
|
end
|
280
287
|
|
@@ -290,7 +297,7 @@ module GraphQL
|
|
290
297
|
graphql_name(type_name)
|
291
298
|
description(builder.merge_descriptions(type_name, types_by_location))
|
292
299
|
|
293
|
-
possible_names = types_by_location.values.flat_map { _1.possible_types.map(&:graphql_name) }.uniq
|
300
|
+
possible_names = types_by_location.values.flat_map { _1.possible_types.map(&:graphql_name) }.tap(&:uniq!)
|
294
301
|
possible_types(*possible_names.map { builder.build_type_binding(_1) })
|
295
302
|
builder.build_merged_directives(type_name, types_by_location, self)
|
296
303
|
end
|
@@ -343,7 +350,7 @@ module GraphQL
|
|
343
350
|
end
|
344
351
|
end
|
345
352
|
|
346
|
-
def build_merged_arguments(type_name, members_by_location, owner, field_name: nil)
|
353
|
+
def build_merged_arguments(type_name, members_by_location, owner, field_name: nil, directive_name: nil)
|
347
354
|
# "argument_name" => "location" => argument
|
348
355
|
args_by_name_location = members_by_location.each_with_object({}) do |(location, member_candidate), memo|
|
349
356
|
member_candidate.arguments.each do |argument_name, argument|
|
@@ -369,7 +376,7 @@ module GraphQL
|
|
369
376
|
|
370
377
|
kwargs = {}
|
371
378
|
default_values_by_location = arguments_by_location.each_with_object({}) do |(location, argument), memo|
|
372
|
-
next if argument.default_value
|
379
|
+
next if argument.default_value == NO_DEFAULT_VALUE
|
373
380
|
memo[location] = argument.default_value
|
374
381
|
end
|
375
382
|
|
@@ -378,7 +385,8 @@ module GraphQL
|
|
378
385
|
type_name: type_name,
|
379
386
|
field_name: field_name,
|
380
387
|
argument_name: argument_name,
|
381
|
-
|
388
|
+
directive_name: directive_name,
|
389
|
+
}.tap(&:compact!))
|
382
390
|
end
|
383
391
|
|
384
392
|
type = merge_value_types(type_name, value_types, argument_name: argument_name, field_name: field_name)
|
@@ -430,7 +438,7 @@ module GraphQL
|
|
430
438
|
enum_value: enum_value,
|
431
439
|
directive_name: directive_name,
|
432
440
|
kwarg_name: kwarg_name,
|
433
|
-
}.compact!)
|
441
|
+
}.tap(&:compact!))
|
434
442
|
end
|
435
443
|
|
436
444
|
owner.directive(directive_class, **kwargs)
|
@@ -438,7 +446,7 @@ module GraphQL
|
|
438
446
|
end
|
439
447
|
|
440
448
|
def merge_value_types(type_name, type_candidates, field_name: nil, argument_name: nil)
|
441
|
-
path = [type_name, field_name, argument_name].compact.join(".")
|
449
|
+
path = [type_name, field_name, argument_name].tap(&:compact!).join(".")
|
442
450
|
alt_structures = type_candidates.map { Util.flatten_type_structure(_1) }
|
443
451
|
basis_structure = alt_structures.shift
|
444
452
|
|
@@ -475,7 +483,7 @@ module GraphQL
|
|
475
483
|
field_name: field_name,
|
476
484
|
argument_name: argument_name,
|
477
485
|
enum_value: enum_value,
|
478
|
-
}.compact!)
|
486
|
+
}.tap(&:compact!))
|
479
487
|
end
|
480
488
|
|
481
489
|
def merge_deprecations(type_name, members_by_location, field_name: nil, argument_name: nil, enum_value: nil)
|
@@ -485,7 +493,7 @@ module GraphQL
|
|
485
493
|
field_name: field_name,
|
486
494
|
argument_name: argument_name,
|
487
495
|
enum_value: enum_value,
|
488
|
-
}.compact!)
|
496
|
+
}.tap(&:compact!))
|
489
497
|
end
|
490
498
|
|
491
499
|
def extract_boundaries(type_name, types_by_location)
|
@@ -16,7 +16,7 @@ module GraphQL
|
|
16
16
|
|
17
17
|
if op.if_type
|
18
18
|
# operations planned around unused fragment conditions should not trigger requests
|
19
|
-
origin_set.select! { _1[
|
19
|
+
origin_set.select! { _1[ExportSelection.typename_node.alias] == op.if_type }
|
20
20
|
end
|
21
21
|
|
22
22
|
memo[op] = origin_set if origin_set.any?
|
@@ -94,9 +94,9 @@ module GraphQL
|
|
94
94
|
end
|
95
95
|
|
96
96
|
def build_key(key, origin_obj, federation: false)
|
97
|
-
key_value = JSON.generate(origin_obj[
|
97
|
+
key_value = JSON.generate(origin_obj[ExportSelection.key(key)])
|
98
98
|
if federation
|
99
|
-
"{ __typename: \"#{origin_obj[
|
99
|
+
"{ __typename: \"#{origin_obj[ExportSelection.typename_node.alias]}\", #{key}: #{key_value} }"
|
100
100
|
else
|
101
101
|
key_value
|
102
102
|
end
|
@@ -160,7 +160,8 @@ module GraphQL
|
|
160
160
|
errors_result.concat(pathed_errors_by_object_id.values)
|
161
161
|
end
|
162
162
|
end
|
163
|
-
|
163
|
+
|
164
|
+
errors_result.tap(&:flatten!)
|
164
165
|
end
|
165
166
|
|
166
167
|
private
|
@@ -4,18 +4,18 @@ module GraphQL
|
|
4
4
|
module Stitching
|
5
5
|
# Builds hidden selection fields added by stitiching code,
|
6
6
|
# used to request operational data about resolved objects.
|
7
|
-
class
|
8
|
-
|
7
|
+
class ExportSelection
|
8
|
+
EXPORT_PREFIX = "_export_"
|
9
9
|
|
10
10
|
class << self
|
11
11
|
def key?(name)
|
12
12
|
return false unless name
|
13
13
|
|
14
|
-
name.start_with?(
|
14
|
+
name.start_with?(EXPORT_PREFIX)
|
15
15
|
end
|
16
16
|
|
17
17
|
def key(name)
|
18
|
-
"#{
|
18
|
+
"#{EXPORT_PREFIX}#{name}"
|
19
19
|
end
|
20
20
|
|
21
21
|
def key_node(field_name)
|
@@ -42,7 +42,7 @@ module GraphQL
|
|
42
42
|
# Adjoining selections not available here get split off into new entrypoints (C).
|
43
43
|
# B.3) Collect all variable definitions used within the filtered selection.
|
44
44
|
# These specify which request variables to pass along with each step.
|
45
|
-
# B.4) Add a `__typename`
|
45
|
+
# B.4) Add a `__typename` export to abstracts and types that implement fragments.
|
46
46
|
# This provides resolved type information used during execution.
|
47
47
|
#
|
48
48
|
# C) Delegate adjoining selections to new entrypoint locations.
|
@@ -199,7 +199,9 @@ module GraphQL
|
|
199
199
|
input_selections.each do |node|
|
200
200
|
case node
|
201
201
|
when GraphQL::Language::Nodes::Field
|
202
|
-
if node.
|
202
|
+
if node.alias&.start_with?(ExportSelection::EXPORT_PREFIX)
|
203
|
+
raise StitchingError, %(Alias "#{node.alias}" is not allowed because "#{ExportSelection::EXPORT_PREFIX}" is a reserved prefix.)
|
204
|
+
elsif node.name == TYPENAME
|
203
205
|
locale_selections << node
|
204
206
|
next
|
205
207
|
end
|
@@ -257,10 +259,10 @@ module GraphQL
|
|
257
259
|
end
|
258
260
|
end
|
259
261
|
|
260
|
-
# B.4) Add a `__typename`
|
262
|
+
# B.4) Add a `__typename` export to abstracts and types that implement
|
261
263
|
# fragments so that resolved type information is available during execution.
|
262
264
|
if requires_typename
|
263
|
-
locale_selections <<
|
265
|
+
locale_selections << ExportSelection.typename_node
|
264
266
|
end
|
265
267
|
|
266
268
|
if remote_selections
|
@@ -274,18 +276,18 @@ module GraphQL
|
|
274
276
|
routes.each_value do |route|
|
275
277
|
route.reduce(locale_selections) do |parent_selections, boundary|
|
276
278
|
# E.1) Add the key of each boundary query into the prior location's selection set.
|
277
|
-
foreign_key =
|
279
|
+
foreign_key = ExportSelection.key(boundary.key)
|
278
280
|
has_key = false
|
279
281
|
has_typename = false
|
280
282
|
|
281
283
|
parent_selections.each do |node|
|
282
284
|
next unless node.is_a?(GraphQL::Language::Nodes::Field)
|
283
285
|
has_key ||= node.alias == foreign_key
|
284
|
-
has_typename ||= node.alias ==
|
286
|
+
has_typename ||= node.alias == ExportSelection.typename_node.alias
|
285
287
|
end
|
286
288
|
|
287
|
-
parent_selections <<
|
288
|
-
parent_selections <<
|
289
|
+
parent_selections << ExportSelection.key_node(boundary.key) unless has_key
|
290
|
+
parent_selections << ExportSelection.typename_node unless has_typename
|
289
291
|
|
290
292
|
# E.2) Add a planner step for each new entrypoint location.
|
291
293
|
add_step(
|
@@ -4,14 +4,13 @@ module GraphQL
|
|
4
4
|
module Stitching
|
5
5
|
class Request
|
6
6
|
SUPPORTED_OPERATIONS = ["query", "mutation"].freeze
|
7
|
+
SKIP_INCLUDE_DIRECTIVE = /@(?:skip|include)/
|
7
8
|
|
8
9
|
attr_reader :document, :variables, :operation_name, :context
|
9
10
|
|
10
11
|
def initialize(document, operation_name: nil, variables: nil, context: nil)
|
11
|
-
@may_contain_runtime_directives = true
|
12
|
-
|
13
12
|
@document = if document.is_a?(String)
|
14
|
-
@
|
13
|
+
@string = document
|
15
14
|
GraphQL.parse(document)
|
16
15
|
else
|
17
16
|
document
|
@@ -23,13 +22,21 @@ module GraphQL
|
|
23
22
|
end
|
24
23
|
|
25
24
|
def string
|
26
|
-
@string
|
25
|
+
@string || normalized_string
|
26
|
+
end
|
27
|
+
|
28
|
+
def normalized_string
|
29
|
+
@normalized_string ||= @document.to_query_string
|
27
30
|
end
|
28
31
|
|
29
32
|
def digest
|
30
33
|
@digest ||= Digest::SHA2.hexdigest(string)
|
31
34
|
end
|
32
35
|
|
36
|
+
def normalized_digest
|
37
|
+
@normalized_digest ||= Digest::SHA2.hexdigest(normalized_string)
|
38
|
+
end
|
39
|
+
|
33
40
|
def operation
|
34
41
|
@operation ||= begin
|
35
42
|
operation_defs = @document.definitions.select do |d|
|
@@ -69,18 +76,15 @@ module GraphQL
|
|
69
76
|
|
70
77
|
def prepare!
|
71
78
|
operation.variables.each do |v|
|
72
|
-
@variables[v.name]
|
79
|
+
@variables[v.name] = v.default_value if @variables[v.name].nil? && !v.default_value.nil?
|
73
80
|
end
|
74
81
|
|
75
|
-
if @
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
@
|
80
|
-
@
|
81
|
-
@operation = nil
|
82
|
-
@variable_definitions = nil
|
83
|
-
@fragment_definitions = nil
|
82
|
+
if @string.nil? || @string.match?(SKIP_INCLUDE_DIRECTIVE)
|
83
|
+
SkipInclude.render(@document, @variables) do |modified_ast|
|
84
|
+
@document = modified_ast
|
85
|
+
@string = @normalized_string = nil
|
86
|
+
@digest = @normalized_digest = nil
|
87
|
+
@operation = @operation_directives = @variable_definitions = nil
|
84
88
|
end
|
85
89
|
end
|
86
90
|
|
@@ -4,7 +4,7 @@
|
|
4
4
|
module GraphQL
|
5
5
|
module Stitching
|
6
6
|
# Shapes the final results payload to the request selection and schema definition.
|
7
|
-
# This eliminates unrequested
|
7
|
+
# This eliminates unrequested export selections and applies null bubbling.
|
8
8
|
class Shaper
|
9
9
|
def initialize(supergraph:, request:)
|
10
10
|
@supergraph = supergraph
|
@@ -21,8 +21,8 @@ module GraphQL
|
|
21
21
|
def resolve_object_scope(raw_object, parent_type, selections, typename = nil)
|
22
22
|
return nil if raw_object.nil?
|
23
23
|
|
24
|
-
typename ||= raw_object[
|
25
|
-
raw_object.reject! { |key, _v|
|
24
|
+
typename ||= raw_object[ExportSelection.typename_node.alias]
|
25
|
+
raw_object.reject! { |key, _v| ExportSelection.key?(key) }
|
26
26
|
|
27
27
|
selections.each do |node|
|
28
28
|
case node
|
@@ -15,7 +15,11 @@ module GraphQL
|
|
15
15
|
definition
|
16
16
|
end
|
17
17
|
|
18
|
-
return document
|
18
|
+
return document unless changed
|
19
|
+
|
20
|
+
document = document.merge(definitions: definitions)
|
21
|
+
yield(document) if block_given?
|
22
|
+
document
|
19
23
|
end
|
20
24
|
|
21
25
|
private
|
@@ -35,7 +39,7 @@ module GraphQL
|
|
35
39
|
end
|
36
40
|
|
37
41
|
if filtered_selections.none?
|
38
|
-
filtered_selections <<
|
42
|
+
filtered_selections << ExportSelection.typename_node
|
39
43
|
end
|
40
44
|
|
41
45
|
if changed
|
data/lib/graphql/stitching.rb
CHANGED
@@ -28,12 +28,12 @@ require_relative "stitching/boundary"
|
|
28
28
|
require_relative "stitching/client"
|
29
29
|
require_relative "stitching/composer"
|
30
30
|
require_relative "stitching/executor"
|
31
|
+
require_relative "stitching/export_selection"
|
31
32
|
require_relative "stitching/http_executable"
|
32
33
|
require_relative "stitching/plan"
|
33
34
|
require_relative "stitching/planner_step"
|
34
35
|
require_relative "stitching/planner"
|
35
36
|
require_relative "stitching/request"
|
36
|
-
require_relative "stitching/selection_hint"
|
37
37
|
require_relative "stitching/shaper"
|
38
38
|
require_relative "stitching/skip_include"
|
39
39
|
require_relative "stitching/util"
|
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.0.
|
4
|
+
version: 1.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Greg MacWilliam
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-11-
|
11
|
+
date: 2023-11-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: graphql
|
@@ -106,12 +106,12 @@ files:
|
|
106
106
|
- lib/graphql/stitching/executor.rb
|
107
107
|
- lib/graphql/stitching/executor/boundary_source.rb
|
108
108
|
- lib/graphql/stitching/executor/root_source.rb
|
109
|
+
- lib/graphql/stitching/export_selection.rb
|
109
110
|
- lib/graphql/stitching/http_executable.rb
|
110
111
|
- lib/graphql/stitching/plan.rb
|
111
112
|
- lib/graphql/stitching/planner.rb
|
112
113
|
- lib/graphql/stitching/planner_step.rb
|
113
114
|
- lib/graphql/stitching/request.rb
|
114
|
-
- lib/graphql/stitching/selection_hint.rb
|
115
115
|
- lib/graphql/stitching/shaper.rb
|
116
116
|
- lib/graphql/stitching/skip_include.rb
|
117
117
|
- lib/graphql/stitching/supergraph.rb
|