@@ -51,7 +51,7 @@ class Query
5151 explicit Query (std::string_view host, std::string_view port, std::string_view target,
5252 int version) noexcept ;
5353
54- std::future<std::string> getRelay (std::string&& queryArg,
54+ std::future<std::optional<std:: string> > getRelay (std::string&& queryArg,
5555 std::optional<std::string>&& operationNameArg,
5656 std::optional<std::string>&& variablesArg) const ;
5757
@@ -73,7 +73,7 @@ Query::Query(
7373
7474// Based on:
7575// https://www.boost.org/doc/libs/1_82_0/libs/beast/example/http/client/awaitable/http_client_awaitable.cpp
76- std::future<std::string> Query::getRelay (std::string&& queryArg,
76+ std::future<std::optional<std:: string> > Query::getRelay (std::string&& queryArg,
7777 std::optional<std::string>&& operationNameArg, std::optional<std::string>&& variablesArg) const
7878{
7979 response::Value payload { response::Type::Map };
@@ -99,7 +99,7 @@ std::future<std::string> Query::getRelay(std::string&& queryArg,
9999 const char * port,
100100 const char * target,
101101 int version,
102- std::string requestBody) -> net::awaitable<std::string> {
102+ std::string requestBody) -> net::awaitable<std::optional<std:: string> > {
103103 // These objects perform our I/O. They use an executor with a default completion token
104104 // of use_awaitable. This makes our code easy, but will use exceptions as the default
105105 // error handling, i.e. if the connection drops, we might see an exception.
@@ -150,7 +150,7 @@ std::future<std::string> Query::getRelay(std::string&& queryArg,
150150 throw boost::system::system_error (ec, " shutdown" );
151151 }
152152
153- co_return std::string { std::move (res.body ()) } ;
153+ co_return std::make_optional<std:: string>( std::move (res.body ())) ;
154154 }(m_host.c_str (), m_port.c_str (), m_target.c_str (), m_version, std::move (requestBody)),
155155 net::use_future);
156156
@@ -182,8 +182,78 @@ int main(int argc, char** argv)
182182 auto serviceResponse = client::parseServiceResponse (
183183 service->resolve ({ query, GetOperationName (), std::move (variables), launch }).get ());
184184 auto result = client::query::relayQuery::parseResponse (std::move (serviceResponse.data ));
185+ auto errors = std::move (serviceResponse.errors );
185186
186- std::cout << result.relay << std::endl;
187+ if (result.relay )
188+ {
189+ std::cout << *result.relay << std::endl;
190+ }
191+
192+ if (!errors.empty ())
193+ {
194+ std::cerr << " Errors executing query:" << std::endl << GetRequestText () << std::endl;
195+
196+ for (const auto & error : errors)
197+ {
198+ std::cerr << " Error: " << error.message ;
199+
200+ if (!error.locations .empty ())
201+ {
202+ bool firstLocation = true ;
203+
204+ std::cerr << " , Locations: [" ;
205+
206+ for (const auto & location : error.locations )
207+ {
208+ if (!firstLocation)
209+ {
210+ std::cerr << " , " ;
211+ }
212+
213+ firstLocation = false ;
214+
215+ std::cerr << " (line: " << location.line << " , column: " << location.column
216+ << " )" ;
217+ }
218+
219+ std::cerr << " ]" ;
220+ }
221+
222+ if (!error.path .empty ())
223+ {
224+ bool firstSegment = true ;
225+
226+ std::cerr << " , Path: " ;
227+
228+ for (const auto & segment : error.path )
229+ {
230+ std::visit (
231+ [firstSegment](const auto & value) noexcept {
232+ using _Type = std::decay_t <decltype (value)>;
233+
234+ if constexpr (std::is_same_v<std::string, _Type>)
235+ {
236+ if (!firstSegment)
237+ {
238+ std::cerr << " /" ;
239+ }
240+
241+ std::cerr << value;
242+ }
243+ else if constexpr (std::is_same_v<int , _Type>)
244+ {
245+ std::cerr << " [" << value << " ]" ;
246+ }
247+ },
248+ segment);
249+
250+ firstSegment = false ;
251+ }
252+ }
253+
254+ std::cerr << std::endl;
255+ }
256+ }
187257 }
188258 catch (const std::runtime_error& ex)
189259 {
0 commit comments