graphql-stitching 1.1.1 → 1.2.1
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/.yardopts +5 -0
- data/Gemfile +0 -3
- data/README.md +10 -32
- data/docs/README.md +1 -0
- data/docs/client.md +2 -2
- data/docs/composer.md +1 -1
- data/docs/executor.md +8 -15
- data/docs/http_executable.md +51 -0
- data/docs/planner.md +12 -14
- data/docs/request.md +2 -0
- data/docs/supergraph.md +2 -2
- data/examples/file_uploads/Gemfile +9 -0
- data/examples/file_uploads/Procfile +2 -0
- data/examples/file_uploads/README.md +37 -0
- data/examples/file_uploads/file.txt +1 -0
- data/examples/file_uploads/gateway.rb +37 -0
- data/examples/file_uploads/helpers.rb +62 -0
- data/examples/file_uploads/remote.rb +21 -0
- data/examples/merged_types/Gemfile +8 -0
- data/examples/merged_types/Procfile +3 -0
- data/examples/merged_types/README.md +33 -0
- data/{example → examples/merged_types}/gateway.rb +4 -5
- data/examples/merged_types/remote1.rb +22 -0
- data/examples/merged_types/remote2.rb +22 -0
- data/lib/graphql/stitching/client.rb +9 -19
- data/lib/graphql/stitching/composer/base_validator.rb +3 -3
- data/lib/graphql/stitching/composer/validate_boundaries.rb +3 -3
- data/lib/graphql/stitching/composer/validate_interfaces.rb +3 -4
- data/lib/graphql/stitching/composer.rb +66 -9
- data/lib/graphql/stitching/executor/boundary_source.rb +4 -6
- data/lib/graphql/stitching/executor/root_source.rb +4 -4
- data/lib/graphql/stitching/executor.rb +16 -13
- data/lib/graphql/stitching/export_selection.rb +6 -1
- data/lib/graphql/stitching/http_executable.rb +145 -4
- data/lib/graphql/stitching/planner.rb +3 -3
- data/lib/graphql/stitching/request.rb +66 -4
- data/lib/graphql/stitching/shaper.rb +4 -3
- data/lib/graphql/stitching/skip_include.rb +4 -3
- data/lib/graphql/stitching/supergraph/resolver_directive.rb +17 -0
- data/lib/graphql/stitching/supergraph/source_directive.rb +12 -0
- data/lib/graphql/stitching/supergraph.rb +27 -34
- data/lib/graphql/stitching/util.rb +0 -9
- data/lib/graphql/stitching/version.rb +1 -1
- metadata +20 -7
- data/Procfile +0 -3
- data/example/remote1.rb +0 -26
- data/example/remote2.rb +0 -26
- /data/{example → examples/merged_types}/graphiql.html +0 -0
@@ -6,9 +6,32 @@ module GraphQL
|
|
6
6
|
SUPPORTED_OPERATIONS = ["query", "mutation"].freeze
|
7
7
|
SKIP_INCLUDE_DIRECTIVE = /@(?:skip|include)/
|
8
8
|
|
9
|
-
|
9
|
+
# @return [Supergraph] supergraph instance that resolves the request.
|
10
|
+
attr_reader :supergraph
|
10
11
|
|
11
|
-
|
12
|
+
# @return [GraphQL::Language::Nodes::Document] the parsed GraphQL AST document.
|
13
|
+
attr_reader :document
|
14
|
+
|
15
|
+
# @return [Hash] input variables for the request.
|
16
|
+
attr_reader :variables
|
17
|
+
|
18
|
+
# @return [String] operation name selected for the request.
|
19
|
+
attr_reader :operation_name
|
20
|
+
|
21
|
+
# @return [Hash] contextual object passed through resolver flows.
|
22
|
+
attr_reader :context
|
23
|
+
|
24
|
+
# @return [GraphQL::Schema::Warden] a visibility warden for this request.
|
25
|
+
attr_reader :warden
|
26
|
+
|
27
|
+
# Creates a new supergraph request.
|
28
|
+
# @param supergraph [Supergraph] supergraph instance that resolves the request.
|
29
|
+
# @param document [String, GraphQL::Language::Nodes::Document] the request string or parsed AST.
|
30
|
+
# @param operation_name [String, nil] operation name selected for the request.
|
31
|
+
# @param variables [Hash, nil] input variables for the request.
|
32
|
+
# @param context [Hash, nil] a contextual object passed through resolver flows.
|
33
|
+
def initialize(supergraph, document, operation_name: nil, variables: nil, context: nil)
|
34
|
+
@supergraph = supergraph
|
12
35
|
@string = nil
|
13
36
|
@digest = nil
|
14
37
|
@normalized_string = nil
|
@@ -17,6 +40,7 @@ module GraphQL
|
|
17
40
|
@operation_directives = nil
|
18
41
|
@variable_definitions = nil
|
19
42
|
@fragment_definitions = nil
|
43
|
+
@plan = nil
|
20
44
|
|
21
45
|
@document = if document.is_a?(String)
|
22
46
|
@string = document
|
@@ -27,25 +51,34 @@ module GraphQL
|
|
27
51
|
|
28
52
|
@operation_name = operation_name
|
29
53
|
@variables = variables || {}
|
30
|
-
|
54
|
+
|
55
|
+
@query = GraphQL::Query.new(@supergraph.schema, document: @document, context: context)
|
56
|
+
@warden = @query.warden
|
57
|
+
@context = @query.context
|
58
|
+
@context[:request] = self
|
31
59
|
end
|
32
60
|
|
61
|
+
# @return [String] the original document string, or a print of the parsed AST document.
|
33
62
|
def string
|
34
63
|
@string || normalized_string
|
35
64
|
end
|
36
65
|
|
66
|
+
# @return [String] a print of the parsed AST document with consistent whitespace.
|
37
67
|
def normalized_string
|
38
68
|
@normalized_string ||= @document.to_query_string
|
39
69
|
end
|
40
70
|
|
71
|
+
# @return [String] a digest of the original document string. Generally faster but less consistent.
|
41
72
|
def digest
|
42
73
|
@digest ||= Digest::SHA2.hexdigest(string)
|
43
74
|
end
|
44
75
|
|
76
|
+
# @return [String] a digest of the normalized document string. Slower but more consistent.
|
45
77
|
def normalized_digest
|
46
78
|
@normalized_digest ||= Digest::SHA2.hexdigest(normalized_string)
|
47
79
|
end
|
48
80
|
|
81
|
+
# @return [GraphQL::Language::Nodes::OperationDefinition] The selected root operation for the request.
|
49
82
|
def operation
|
50
83
|
@operation ||= begin
|
51
84
|
operation_defs = @document.definitions.select do |d|
|
@@ -64,6 +97,7 @@ module GraphQL
|
|
64
97
|
end
|
65
98
|
end
|
66
99
|
|
100
|
+
# @return [String] A string of directives applied to the root operation. These are passed through in all subgraph requests.
|
67
101
|
def operation_directives
|
68
102
|
@operation_directives ||= if operation.directives.any?
|
69
103
|
printer = GraphQL::Language::Printer.new
|
@@ -71,18 +105,27 @@ module GraphQL
|
|
71
105
|
end
|
72
106
|
end
|
73
107
|
|
108
|
+
# @return [Hash<String, GraphQL::Language::Nodes::AbstractNode>] map of variable names to AST type definitions.
|
74
109
|
def variable_definitions
|
75
110
|
@variable_definitions ||= operation.variables.each_with_object({}) do |v, memo|
|
76
111
|
memo[v.name] = v.type
|
77
112
|
end
|
78
113
|
end
|
79
114
|
|
115
|
+
# @return [Hash<String, GraphQL::Language::Nodes::FragmentDefinition>] map of fragment names to their AST definitions.
|
80
116
|
def fragment_definitions
|
81
117
|
@fragment_definitions ||= @document.definitions.each_with_object({}) do |d, memo|
|
82
118
|
memo[d.name] = d if d.is_a?(GraphQL::Language::Nodes::FragmentDefinition)
|
83
119
|
end
|
84
120
|
end
|
85
121
|
|
122
|
+
# Validates the request using the combined supergraph schema.
|
123
|
+
def validate
|
124
|
+
result = @supergraph.static_validator.validate(@query)
|
125
|
+
result[:errors]
|
126
|
+
end
|
127
|
+
|
128
|
+
# Prepares the request for stitching by rendering variable defaults and applying @skip/@include conditionals.
|
86
129
|
def prepare!
|
87
130
|
operation.variables.each do |v|
|
88
131
|
@variables[v.name] = v.default_value if @variables[v.name].nil? && !v.default_value.nil?
|
@@ -93,12 +136,31 @@ module GraphQL
|
|
93
136
|
@document = modified_ast
|
94
137
|
@string = @normalized_string = nil
|
95
138
|
@digest = @normalized_digest = nil
|
96
|
-
@operation = @operation_directives = @variable_definitions = nil
|
139
|
+
@operation = @operation_directives = @variable_definitions = @plan = nil
|
97
140
|
end
|
98
141
|
end
|
99
142
|
|
100
143
|
self
|
101
144
|
end
|
145
|
+
|
146
|
+
# Gets and sets the query plan for the request. Assigned query plans may pull from cache.
|
147
|
+
# @param new_plan [Plan, nil] a cached query plan for the request.
|
148
|
+
# @return [Plan] query plan for the request.
|
149
|
+
def plan(new_plan = nil)
|
150
|
+
if new_plan
|
151
|
+
raise StitchingError, "Plan must be a `GraphQL::Stitching::Plan`." unless new_plan.is_a?(Plan)
|
152
|
+
@plan = new_plan
|
153
|
+
else
|
154
|
+
@plan ||= GraphQL::Stitching::Planner.new(self).perform
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# Executes the request and returns the rendered response.
|
159
|
+
# @param raw [Boolean] specifies the result should be unshaped without pruning or null bubbling. Useful for debugging.
|
160
|
+
# @return [Hash] the rendered GraphQL response with "data" and "errors" sections.
|
161
|
+
def execute(raw: false)
|
162
|
+
GraphQL::Stitching::Executor.new(self).perform(raw: raw)
|
163
|
+
end
|
102
164
|
end
|
103
165
|
end
|
104
166
|
end
|
@@ -5,10 +5,11 @@ module GraphQL
|
|
5
5
|
module Stitching
|
6
6
|
# Shapes the final results payload to the request selection and schema definition.
|
7
7
|
# This eliminates unrequested export selections and applies null bubbling.
|
8
|
+
# @api private
|
8
9
|
class Shaper
|
9
|
-
def initialize(
|
10
|
-
@supergraph = supergraph
|
10
|
+
def initialize(request)
|
11
11
|
@request = request
|
12
|
+
@supergraph = request.supergraph
|
12
13
|
@root_type = nil
|
13
14
|
end
|
14
15
|
|
@@ -117,7 +118,7 @@ module GraphQL
|
|
117
118
|
def typename_in_type?(typename, type)
|
118
119
|
return true if type.graphql_name == typename
|
119
120
|
|
120
|
-
type.kind.abstract? && @
|
121
|
+
type.kind.abstract? && @request.warden.possible_types(type).any? do |t|
|
121
122
|
t.graphql_name == typename
|
122
123
|
end
|
123
124
|
end
|
@@ -2,11 +2,12 @@
|
|
2
2
|
|
3
3
|
module GraphQL
|
4
4
|
module Stitching
|
5
|
+
# Faster implementation of an AST visitor for prerendering
|
6
|
+
# @skip and @include conditional directives into a document.
|
7
|
+
# This avoids unnecessary planning steps, and prepares result shaping.
|
8
|
+
# @api private
|
5
9
|
class SkipInclude
|
6
10
|
class << self
|
7
|
-
# Faster implementation of an AST visitor for prerendering
|
8
|
-
# @skip and @include conditional directives into a document.
|
9
|
-
# This avoids unnecessary planning steps, and prepares result shaping.
|
10
11
|
def render(document, variables)
|
11
12
|
changed = false
|
12
13
|
definitions = document.definitions.map do |original_definition|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL::Stitching
|
4
|
+
class Supergraph
|
5
|
+
class ResolverDirective < GraphQL::Schema::Directive
|
6
|
+
graphql_name "resolver"
|
7
|
+
locations OBJECT, INTERFACE, UNION
|
8
|
+
argument :location, String, required: true
|
9
|
+
argument :key, String, required: true
|
10
|
+
argument :field, String, required: true
|
11
|
+
argument :arg, String, required: true
|
12
|
+
argument :list, Boolean, required: false
|
13
|
+
argument :federation, Boolean, required: false
|
14
|
+
repeatable true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL::Stitching
|
4
|
+
class Supergraph
|
5
|
+
class SourceDirective < GraphQL::Schema::Directive
|
6
|
+
graphql_name "source"
|
7
|
+
locations FIELD_DEFINITION
|
8
|
+
argument :location, String, required: true
|
9
|
+
repeatable true
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -1,29 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "./supergraph/resolver_directive"
|
4
|
+
require_relative "./supergraph/source_directive"
|
5
|
+
|
3
6
|
module GraphQL
|
4
7
|
module Stitching
|
5
8
|
class Supergraph
|
6
9
|
SUPERGRAPH_LOCATION = "__super"
|
7
10
|
|
8
|
-
class ResolverDirective < GraphQL::Schema::Directive
|
9
|
-
graphql_name "resolver"
|
10
|
-
locations OBJECT, INTERFACE, UNION
|
11
|
-
argument :location, String, required: true
|
12
|
-
argument :key, String, required: true
|
13
|
-
argument :field, String, required: true
|
14
|
-
argument :arg, String, required: true
|
15
|
-
argument :list, Boolean, required: false
|
16
|
-
argument :federation, Boolean, required: false
|
17
|
-
repeatable true
|
18
|
-
end
|
19
|
-
|
20
|
-
class SourceDirective < GraphQL::Schema::Directive
|
21
|
-
graphql_name "source"
|
22
|
-
locations FIELD_DEFINITION
|
23
|
-
argument :location, String, required: true
|
24
|
-
repeatable true
|
25
|
-
end
|
26
|
-
|
27
11
|
class << self
|
28
12
|
def validate_executable!(location, executable)
|
29
13
|
return true if executable.is_a?(Class) && executable <= GraphQL::Schema
|
@@ -88,19 +72,27 @@ module GraphQL
|
|
88
72
|
end
|
89
73
|
end
|
90
74
|
|
91
|
-
|
75
|
+
# @return [GraphQL::Schema] the composed schema for the supergraph.
|
76
|
+
attr_reader :schema
|
77
|
+
|
78
|
+
# @return [Hash<String, Executable>] a map of executable resources by location.
|
79
|
+
attr_reader :executables
|
92
80
|
|
93
|
-
|
81
|
+
attr_reader :boundaries, :locations_by_type_and_field
|
82
|
+
|
83
|
+
def initialize(schema:, fields: {}, boundaries: {}, executables: {})
|
94
84
|
@schema = schema
|
85
|
+
@schema.use(GraphQL::Schema::AlwaysVisible)
|
86
|
+
|
95
87
|
@boundaries = boundaries
|
96
|
-
@possible_keys_by_type = {}
|
97
|
-
@possible_keys_by_type_and_location = {}
|
98
|
-
@memoized_schema_possible_types = {}
|
99
|
-
@memoized_schema_fields = {}
|
100
|
-
@memoized_introspection_types = nil
|
101
|
-
@memoized_schema_types = nil
|
102
88
|
@fields_by_type_and_location = nil
|
103
89
|
@locations_by_type = nil
|
90
|
+
@memoized_introspection_types = nil
|
91
|
+
@memoized_schema_fields = {}
|
92
|
+
@memoized_schema_types = nil
|
93
|
+
@possible_keys_by_type = {}
|
94
|
+
@possible_keys_by_type_and_location = {}
|
95
|
+
@static_validator = nil
|
104
96
|
|
105
97
|
# add introspection types into the fields mapping
|
106
98
|
@locations_by_type_and_field = memoized_introspection_types.each_with_object(fields) do |(type_name, type), memo|
|
@@ -172,6 +164,11 @@ module GraphQL
|
|
172
164
|
@schema.to_definition
|
173
165
|
end
|
174
166
|
|
167
|
+
# @return [GraphQL::StaticValidation::Validator] static validator for the supergraph schema.
|
168
|
+
def static_validator
|
169
|
+
@static_validator ||= @schema.static_validator
|
170
|
+
end
|
171
|
+
|
175
172
|
def fields
|
176
173
|
@locations_by_type_and_field.reject { |k, _v| memoized_introspection_types[k] }
|
177
174
|
end
|
@@ -188,10 +185,6 @@ module GraphQL
|
|
188
185
|
@memoized_schema_types ||= @schema.types
|
189
186
|
end
|
190
187
|
|
191
|
-
def memoized_schema_possible_types(type_name)
|
192
|
-
@memoized_schema_possible_types[type_name] ||= @schema.possible_types(memoized_schema_types[type_name])
|
193
|
-
end
|
194
|
-
|
195
188
|
def memoized_schema_fields(type_name)
|
196
189
|
@memoized_schema_fields[type_name] ||= begin
|
197
190
|
fields = memoized_schema_types[type_name].fields
|
@@ -209,7 +202,7 @@ module GraphQL
|
|
209
202
|
end
|
210
203
|
end
|
211
204
|
|
212
|
-
def execute_at_location(location, source, variables,
|
205
|
+
def execute_at_location(location, source, variables, request)
|
213
206
|
executable = executables[location]
|
214
207
|
|
215
208
|
if executable.nil?
|
@@ -218,11 +211,11 @@ module GraphQL
|
|
218
211
|
executable.execute(
|
219
212
|
query: source,
|
220
213
|
variables: variables,
|
221
|
-
context: context.frozen? ? context.dup : context,
|
214
|
+
context: request.context.frozen? ? request.context.dup : request.context,
|
222
215
|
validate: false,
|
223
216
|
)
|
224
217
|
elsif executable.respond_to?(:call)
|
225
|
-
executable.call(
|
218
|
+
executable.call(request, source, variables)
|
226
219
|
else
|
227
220
|
raise StitchingError, "Missing valid executable for #{location} location."
|
228
221
|
end
|
@@ -12,16 +12,7 @@ module GraphQL
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
GRAPHQL_VERSION = GraphQL::VERSION.split(".").map(&:to_i).freeze
|
16
|
-
|
17
15
|
class << self
|
18
|
-
def graphql_version?(major, minor = nil, patch = nil)
|
19
|
-
result = GRAPHQL_VERSION[0] >= major
|
20
|
-
result &&= GRAPHQL_VERSION[1] >= minor if minor
|
21
|
-
result &&= GRAPHQL_VERSION[2] >= patch if patch
|
22
|
-
result
|
23
|
-
end
|
24
|
-
|
25
16
|
# specifies if a type is a primitive leaf value
|
26
17
|
def is_leaf_type?(type)
|
27
18
|
type.kind.scalar? || type.kind.enum?
|
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.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Greg MacWilliam
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: graphql
|
@@ -74,15 +74,16 @@ extra_rdoc_files: []
|
|
74
74
|
files:
|
75
75
|
- ".github/workflows/ci.yml"
|
76
76
|
- ".gitignore"
|
77
|
+
- ".yardopts"
|
77
78
|
- Gemfile
|
78
79
|
- LICENSE
|
79
|
-
- Procfile
|
80
80
|
- README.md
|
81
81
|
- Rakefile
|
82
82
|
- docs/README.md
|
83
83
|
- docs/client.md
|
84
84
|
- docs/composer.md
|
85
85
|
- docs/executor.md
|
86
|
+
- docs/http_executable.md
|
86
87
|
- docs/images/library.png
|
87
88
|
- docs/images/merging.png
|
88
89
|
- docs/images/stitching.png
|
@@ -90,10 +91,20 @@ files:
|
|
90
91
|
- docs/planner.md
|
91
92
|
- docs/request.md
|
92
93
|
- docs/supergraph.md
|
93
|
-
-
|
94
|
-
-
|
95
|
-
-
|
96
|
-
-
|
94
|
+
- examples/file_uploads/Gemfile
|
95
|
+
- examples/file_uploads/Procfile
|
96
|
+
- examples/file_uploads/README.md
|
97
|
+
- examples/file_uploads/file.txt
|
98
|
+
- examples/file_uploads/gateway.rb
|
99
|
+
- examples/file_uploads/helpers.rb
|
100
|
+
- examples/file_uploads/remote.rb
|
101
|
+
- examples/merged_types/Gemfile
|
102
|
+
- examples/merged_types/Procfile
|
103
|
+
- examples/merged_types/README.md
|
104
|
+
- examples/merged_types/gateway.rb
|
105
|
+
- examples/merged_types/graphiql.html
|
106
|
+
- examples/merged_types/remote1.rb
|
107
|
+
- examples/merged_types/remote2.rb
|
97
108
|
- gemfiles/graphql_1.13.9.gemfile
|
98
109
|
- graphql-stitching.gemspec
|
99
110
|
- lib/graphql/stitching.rb
|
@@ -115,6 +126,8 @@ files:
|
|
115
126
|
- lib/graphql/stitching/shaper.rb
|
116
127
|
- lib/graphql/stitching/skip_include.rb
|
117
128
|
- lib/graphql/stitching/supergraph.rb
|
129
|
+
- lib/graphql/stitching/supergraph/resolver_directive.rb
|
130
|
+
- lib/graphql/stitching/supergraph/source_directive.rb
|
118
131
|
- lib/graphql/stitching/util.rb
|
119
132
|
- lib/graphql/stitching/version.rb
|
120
133
|
homepage: https://github.com/gmac/graphql-stitching-ruby
|
data/Procfile
DELETED
data/example/remote1.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'rackup'
|
4
|
-
require 'json'
|
5
|
-
require 'graphql'
|
6
|
-
require_relative '../test/schemas/example'
|
7
|
-
|
8
|
-
class FirstRemoteApp
|
9
|
-
def call(env)
|
10
|
-
req = Rack::Request.new(env)
|
11
|
-
case req.path_info
|
12
|
-
when /graphql/
|
13
|
-
params = JSON.parse(req.body.read)
|
14
|
-
result = Schemas::Example::Storefronts.execute(
|
15
|
-
query: params["query"],
|
16
|
-
variables: params["variables"],
|
17
|
-
operation_name: params["operationName"],
|
18
|
-
)
|
19
|
-
[200, {"content-type" => "application/json"}, [JSON.generate(result)]]
|
20
|
-
else
|
21
|
-
[404, {"content-type" => "text/html"}, ["not found"]]
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
Rackup::Handler.default.run(FirstRemoteApp.new, :Port => 3001)
|
data/example/remote2.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'rackup'
|
4
|
-
require 'json'
|
5
|
-
require 'graphql'
|
6
|
-
require_relative '../test/schemas/example'
|
7
|
-
|
8
|
-
class SecondRemoteApp
|
9
|
-
def call(env)
|
10
|
-
req = Rack::Request.new(env)
|
11
|
-
case req.path_info
|
12
|
-
when /graphql/
|
13
|
-
params = JSON.parse(req.body.read)
|
14
|
-
result = Schemas::Example::Manufacturers.execute(
|
15
|
-
query: params["query"],
|
16
|
-
variables: params["variables"],
|
17
|
-
operation_name: params["operationName"],
|
18
|
-
)
|
19
|
-
[200, {"content-type" => "application/json"}, [JSON.generate(result)]]
|
20
|
-
else
|
21
|
-
[404, {"content-type" => "text/html"}, ["not found"]]
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
Rackup::Handler.default.run(SecondRemoteApp.new, :Port => 3002)
|
File without changes
|