graphql-stitching 1.5.2 → 1.6.0
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/docs/request.md +2 -4
- data/lib/graphql/stitching/client.rb +0 -1
- data/lib/graphql/stitching/executor/shaper.rb +2 -2
- data/lib/graphql/stitching/http_executable.rb +1 -1
- data/lib/graphql/stitching/planner.rb +2 -2
- data/lib/graphql/stitching/request.rb +64 -59
- data/lib/graphql/stitching/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 227a7813eed1050c451d9bbee900305cfbac67aff35baa88f6ba9551535d1e97
|
4
|
+
data.tar.gz: 1533e6109c6a72af3f7d07891714c09a73476ca0a5a7ea53d83cbe829564ace3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8342158a10bc25fb68c833a3366c2fd6e831cf86cccf15a2491067680bb5299700783af57fd5042b394131b48759f077d32f4b210149a2b3cb34e43e3cca77ff
|
7
|
+
data.tar.gz: 7313c93bb8cedf7ac06708a1f7fba6a2c46196982380a28a6d9244cf7320ad0149cb17df8ecb1abe438e14eac08b2f71e154dd9f2d6c3095be8e849c46061e16
|
data/docs/request.md
CHANGED
@@ -15,7 +15,6 @@ request = GraphQL::Stitching::Request.new(
|
|
15
15
|
|
16
16
|
A `Request` provides the following information:
|
17
17
|
|
18
|
-
- `req.document`: parsed AST of the GraphQL source.
|
19
18
|
- `req.variables`: a hash of user-submitted variables.
|
20
19
|
- `req.string`: the original GraphQL source string, or printed document.
|
21
20
|
- `req.digest`: a digest of the request string, hashed by the `Stitching.digest` implementation.
|
@@ -31,6 +30,5 @@ A request manages the flow of stitching behaviors. These are sequenced by the `C
|
|
31
30
|
component, or you may invoke them manually:
|
32
31
|
|
33
32
|
1. `request.validate`: runs static validations on the request using the combined schema.
|
34
|
-
2. `request.
|
35
|
-
3. `request.
|
36
|
-
4. `request.execute`: executes the request, and returns the resulting data.
|
33
|
+
2. `request.plan`: builds a plan for the request. May act as a setter for plans pulled from cache.
|
34
|
+
3. `request.execute`: executes the request, and returns the resulting data.
|
@@ -14,7 +14,7 @@ module GraphQL::Stitching
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def perform!(raw)
|
17
|
-
@root_type = @
|
17
|
+
@root_type = @request.query.root_type_for_operation(@request.operation.operation_type)
|
18
18
|
resolve_object_scope(raw, @root_type, @request.operation.selections, @root_type.graphql_name)
|
19
19
|
end
|
20
20
|
|
@@ -118,7 +118,7 @@ module GraphQL::Stitching
|
|
118
118
|
def typename_in_type?(typename, type)
|
119
119
|
return true if type.graphql_name == typename
|
120
120
|
|
121
|
-
type.kind.abstract? && @
|
121
|
+
type.kind.abstract? && @request.query.possible_types(type).any? do |t|
|
122
122
|
t.graphql_name == typename
|
123
123
|
end
|
124
124
|
end
|
@@ -132,7 +132,7 @@ module GraphQL
|
|
132
132
|
elsif @upload_types.include?(ast_node.name)
|
133
133
|
files_by_path[path.dup] = value
|
134
134
|
else
|
135
|
-
type_def = request.
|
135
|
+
type_def = request.query.get_type(ast_node.name)
|
136
136
|
extract_type_node(type_def, value, files_by_path, path) if type_def&.kind&.input_object?
|
137
137
|
end
|
138
138
|
end
|
@@ -106,7 +106,7 @@ module GraphQL
|
|
106
106
|
|
107
107
|
# A) Group all root selections by their preferred entrypoint locations.
|
108
108
|
def build_root_entrypoints
|
109
|
-
parent_type = @
|
109
|
+
parent_type = @request.query.root_type_for_operation(@request.operation.operation_type)
|
110
110
|
|
111
111
|
case @request.operation.operation_type
|
112
112
|
when QUERY_OP
|
@@ -331,7 +331,7 @@ module GraphQL
|
|
331
331
|
end
|
332
332
|
|
333
333
|
if expanded_selections
|
334
|
-
@
|
334
|
+
@request.query.possible_types(parent_type).each do |possible_type|
|
335
335
|
next unless @supergraph.locations_by_type[possible_type.graphql_name].include?(current_location)
|
336
336
|
|
337
337
|
type_name = GraphQL::Language::Nodes::TypeName.new(name: possible_type.graphql_name)
|
@@ -14,26 +14,21 @@ module GraphQL
|
|
14
14
|
# @return [Supergraph] supergraph instance that resolves the request.
|
15
15
|
attr_reader :supergraph
|
16
16
|
|
17
|
-
# @return [GraphQL::
|
18
|
-
attr_reader :
|
19
|
-
|
20
|
-
# @return [Hash] input variables for the request.
|
21
|
-
attr_reader :variables
|
22
|
-
|
23
|
-
# @return [String] operation name selected for the request.
|
24
|
-
attr_reader :operation_name
|
17
|
+
# @return [GraphQL::Query] query object defining the request.
|
18
|
+
attr_reader :query
|
25
19
|
|
26
20
|
# @return [Hash] contextual object passed through resolver flows.
|
27
21
|
attr_reader :context
|
28
22
|
|
29
23
|
# Creates a new supergraph request.
|
30
24
|
# @param supergraph [Supergraph] supergraph instance that resolves the request.
|
31
|
-
# @param
|
25
|
+
# @param source [String, GraphQL::Language::Nodes::Document] the request string or parsed AST.
|
32
26
|
# @param operation_name [String, nil] operation name selected for the request.
|
33
27
|
# @param variables [Hash, nil] input variables for the request.
|
34
28
|
# @param context [Hash, nil] a contextual object passed through resolver flows.
|
35
|
-
def initialize(supergraph,
|
29
|
+
def initialize(supergraph, source, operation_name: nil, variables: nil, context: nil)
|
36
30
|
@supergraph = supergraph
|
31
|
+
@prepared_document = nil
|
37
32
|
@string = nil
|
38
33
|
@digest = nil
|
39
34
|
@normalized_string = nil
|
@@ -44,29 +39,32 @@ module GraphQL
|
|
44
39
|
@fragment_definitions = nil
|
45
40
|
@plan = nil
|
46
41
|
|
47
|
-
|
48
|
-
|
49
|
-
|
42
|
+
params = {
|
43
|
+
operation_name: operation_name,
|
44
|
+
variables: variables,
|
45
|
+
context: context,
|
46
|
+
}
|
47
|
+
|
48
|
+
if source.is_a?(String)
|
49
|
+
@string = source
|
50
|
+
params[:query] = source
|
50
51
|
else
|
51
|
-
document
|
52
|
+
params[:document] = source
|
52
53
|
end
|
53
54
|
|
54
|
-
@
|
55
|
-
@variables = variables || {}
|
56
|
-
|
57
|
-
@query = GraphQL::Query.new(@supergraph.schema, document: @document, context: context)
|
55
|
+
@query = GraphQL::Query.new(@supergraph.schema, **params)
|
58
56
|
@context = @query.context
|
59
57
|
@context[:request] = self
|
60
58
|
end
|
61
59
|
|
62
60
|
# @return [String] the original document string, or a print of the parsed AST document.
|
63
61
|
def string
|
64
|
-
@string || normalized_string
|
62
|
+
with_prepared_document { @string || normalized_string }
|
65
63
|
end
|
66
64
|
|
67
65
|
# @return [String] a print of the parsed AST document with consistent whitespace.
|
68
66
|
def normalized_string
|
69
|
-
@normalized_string ||=
|
67
|
+
@normalized_string ||= prepared_document.to_query_string
|
70
68
|
end
|
71
69
|
|
72
70
|
# @return [String] a digest of the original document string. Generally faster but less consistent.
|
@@ -81,43 +79,48 @@ module GraphQL
|
|
81
79
|
|
82
80
|
# @return [GraphQL::Language::Nodes::OperationDefinition] The selected root operation for the request.
|
83
81
|
def operation
|
84
|
-
@operation ||=
|
85
|
-
|
82
|
+
@operation ||= with_prepared_document do
|
83
|
+
selected_op = @query.selected_operation
|
84
|
+
raise GraphQL::ExecutionError, "No operation selected" unless selected_op
|
85
|
+
|
86
|
+
@prepared_document.definitions.find do |d|
|
86
87
|
next unless d.is_a?(GraphQL::Language::Nodes::OperationDefinition)
|
87
|
-
@operation_name ? d.name == @operation_name : true
|
88
|
-
end
|
89
88
|
|
90
|
-
|
91
|
-
raise GraphQL::ExecutionError, "Invalid root operation for given name and operation type."
|
92
|
-
elsif operation_defs.length > 1
|
93
|
-
raise GraphQL::ExecutionError, "An operation name is required when sending multiple operations."
|
89
|
+
selected_op.name.nil? || d.name == selected_op.name
|
94
90
|
end
|
91
|
+
end
|
92
|
+
end
|
95
93
|
|
96
|
-
|
94
|
+
def operation_name
|
95
|
+
operation.name
|
96
|
+
end
|
97
|
+
|
98
|
+
# @return [String] A string of directives applied to the root operation. These are passed through in all subgraph requests.
|
99
|
+
def operation_directives
|
100
|
+
@operation_directives ||= if operation.directives.any?
|
101
|
+
printer = GraphQL::Language::Printer.new
|
102
|
+
operation.directives.map { printer.print(_1) }.join(" ")
|
97
103
|
end
|
98
104
|
end
|
99
105
|
|
100
106
|
# @return [Boolean] true if operation type is a query
|
101
107
|
def query?
|
102
|
-
|
108
|
+
@query.query?
|
103
109
|
end
|
104
110
|
|
105
111
|
# @return [Boolean] true if operation type is a mutation
|
106
112
|
def mutation?
|
107
|
-
|
113
|
+
@query.mutation?
|
108
114
|
end
|
109
115
|
|
110
116
|
# @return [Boolean] true if operation type is a subscription
|
111
117
|
def subscription?
|
112
|
-
|
118
|
+
@query.subscription?
|
113
119
|
end
|
114
120
|
|
115
|
-
# @return [String]
|
116
|
-
def
|
117
|
-
@
|
118
|
-
printer = GraphQL::Language::Printer.new
|
119
|
-
operation.directives.map { printer.print(_1) }.join(" ")
|
120
|
-
end
|
121
|
+
# @return [Hash<String, Any>] provided variables hash filled in with default values from definitions
|
122
|
+
def variables
|
123
|
+
@variables || with_prepared_document { @variables }
|
121
124
|
end
|
122
125
|
|
123
126
|
# @return [Hash<String, GraphQL::Language::Nodes::AbstractNode>] map of variable names to AST type definitions.
|
@@ -129,7 +132,7 @@ module GraphQL
|
|
129
132
|
|
130
133
|
# @return [Hash<String, GraphQL::Language::Nodes::FragmentDefinition>] map of fragment names to their AST definitions.
|
131
134
|
def fragment_definitions
|
132
|
-
@fragment_definitions ||=
|
135
|
+
@fragment_definitions ||= prepared_document.definitions.each_with_object({}) do |d, memo|
|
133
136
|
memo[d.name] = d if d.is_a?(GraphQL::Language::Nodes::FragmentDefinition)
|
134
137
|
end
|
135
138
|
end
|
@@ -137,26 +140,7 @@ module GraphQL
|
|
137
140
|
# Validates the request using the combined supergraph schema.
|
138
141
|
# @return [Array<GraphQL::ExecutionError>] an array of static validation errors
|
139
142
|
def validate
|
140
|
-
|
141
|
-
result[:errors]
|
142
|
-
end
|
143
|
-
|
144
|
-
# Prepares the request for stitching by inserting variable defaults and applying @skip/@include conditionals.
|
145
|
-
def prepare!
|
146
|
-
operation.variables.each do |v|
|
147
|
-
@variables[v.name] = v.default_value if @variables[v.name].nil? && !v.default_value.nil?
|
148
|
-
end
|
149
|
-
|
150
|
-
if @string.nil? || @string.match?(SKIP_INCLUDE_DIRECTIVE)
|
151
|
-
SkipInclude.render(@document, @variables) do |modified_ast|
|
152
|
-
@document = modified_ast
|
153
|
-
@string = @normalized_string = nil
|
154
|
-
@digest = @normalized_digest = nil
|
155
|
-
@operation = @operation_directives = @variable_definitions = @plan = nil
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
self
|
143
|
+
@query.static_errors
|
160
144
|
end
|
161
145
|
|
162
146
|
# Gets and sets the query plan for the request. Assigned query plans may pull from a cache,
|
@@ -191,6 +175,27 @@ module GraphQL
|
|
191
175
|
|
192
176
|
private
|
193
177
|
|
178
|
+
# Prepares the request for stitching by applying @skip/@include conditionals.
|
179
|
+
def prepared_document
|
180
|
+
@prepared_document || with_prepared_document { @prepared_document }
|
181
|
+
end
|
182
|
+
|
183
|
+
def with_prepared_document
|
184
|
+
unless @prepared_document
|
185
|
+
@variables = @query.variables.to_h
|
186
|
+
|
187
|
+
@prepared_document = if @string.nil? || @string.match?(SKIP_INCLUDE_DIRECTIVE)
|
188
|
+
changed = false
|
189
|
+
doc = SkipInclude.render(@query.document, @variables) { changed = true }
|
190
|
+
@string = @normalized_string = doc.to_query_string if changed
|
191
|
+
doc
|
192
|
+
else
|
193
|
+
@query.document
|
194
|
+
end
|
195
|
+
end
|
196
|
+
yield
|
197
|
+
end
|
198
|
+
|
194
199
|
# Adds a handler into context for enriching subscription updates with stitched data
|
195
200
|
def add_subscription_update_handler
|
196
201
|
request = self
|
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
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Greg MacWilliam
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-03-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: graphql
|