Skip to content

Commit 633c50b

Browse files
authored
Merge pull request microsoft#331 from wravery/next
fix: use stitched schema for Introspection on root Query
2 parents 29376f2 + 7662396 commit 633c50b

File tree

2 files changed

+77
-24
lines changed

2 files changed

+77
-24
lines changed

include/graphqlservice/GraphQLService.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -830,7 +830,8 @@ class [[nodiscard("unnecessary construction")]] Object : public std::enable_shar
830830
GRAPHQLSERVICE_EXPORT virtual ~Object() = default;
831831

832832
[[nodiscard("unnecessary call")]] GRAPHQLSERVICE_EXPORT std::shared_ptr<Object> StitchObject(
833-
const std::shared_ptr<const Object>& added) const;
833+
const std::shared_ptr<const Object>& added,
834+
const std::shared_ptr<schema::Schema>& schema = {}) const;
834835

835836
[[nodiscard("unnecessary call")]] GRAPHQLSERVICE_EXPORT AwaitableResolver resolve(
836837
const SelectionSetParams& selectionSetParams, const peg::ast_node& selection,

src/GraphQLService.cpp

Lines changed: 75 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
#include "graphqlservice/GraphQLService.h"
55

66
#include "graphqlservice/internal/Grammar.h"
7+
#include "graphqlservice/internal/Introspection.h"
8+
9+
#include "graphqlservice/introspection/SchemaObject.h"
10+
#include "graphqlservice/introspection/TypeObject.h"
711

812
#include "Validation.h"
913

@@ -267,17 +271,17 @@ void await_worker_queue::resumePending()
267271
// Default to immediate synchronous execution.
268272
await_async::await_async()
269273
: _pimpl { std::static_pointer_cast<const Concept>(
270-
std::make_shared<Model<std::suspend_never>>(std::make_shared<std::suspend_never>())) }
274+
std::make_shared<Model<std::suspend_never>>(std::make_shared<std::suspend_never>())) }
271275
{
272276
}
273277

274278
// Implicitly convert a std::launch parameter used with std::async to an awaitable.
275279
await_async::await_async(std::launch launch)
276280
: _pimpl { ((launch & std::launch::async) == std::launch::async)
277281
? std::static_pointer_cast<const Concept>(std::make_shared<Model<await_worker_thread>>(
278-
std::make_shared<await_worker_thread>()))
282+
std::make_shared<await_worker_thread>()))
279283
: std::static_pointer_cast<const Concept>(std::make_shared<Model<std::suspend_never>>(
280-
std::make_shared<std::suspend_never>())) }
284+
std::make_shared<std::suspend_never>())) }
281285
{
282286
}
283287

@@ -1253,21 +1257,53 @@ Object::Object(TypeNames&& typeNames, ResolverMap&& resolvers) noexcept
12531257
{
12541258
}
12551259

1256-
std::shared_ptr<Object> Object::StitchObject(const std::shared_ptr<const Object>& added) const
1260+
std::shared_ptr<Object> Object::StitchObject(const std::shared_ptr<const Object>& added,
1261+
const std::shared_ptr<schema::Schema>& schema /* = {} */) const
12571262
{
12581263
auto typeNames = _typeNames;
1264+
auto resolvers = _resolvers;
12591265

1260-
for (const auto& name : added->_typeNames)
1266+
if (schema && schema->supportsIntrospection())
12611267
{
1262-
typeNames.emplace(name);
1268+
constexpr auto schemaField = R"gql(__schema)gql"sv;
1269+
constexpr auto typeField = R"gql(__type)gql"sv;
1270+
1271+
resolvers.erase(schemaField);
1272+
resolvers.emplace(schemaField, [schema](ResolverParams&& params) {
1273+
return Result<Object>::convert(
1274+
std::static_pointer_cast<Object>(std::make_shared<introspection::object::Schema>(
1275+
std::make_shared<introspection::Schema>(schema))),
1276+
std::move(params));
1277+
});
1278+
1279+
resolvers.erase(typeField);
1280+
resolvers.emplace(typeField, [schema](ResolverParams&& params) {
1281+
auto argName = ModifiedArgument<std::string>::require("name", params.arguments);
1282+
const auto& baseType = schema->LookupType(argName);
1283+
std::shared_ptr<introspection::object::Type> result { baseType
1284+
? std::make_shared<introspection::object::Type>(
1285+
std::make_shared<introspection::Type>(baseType))
1286+
: nullptr };
1287+
1288+
return ModifiedResult<introspection::object::Type>::convert<TypeModifier::Nullable>(
1289+
result,
1290+
std::move(params));
1291+
});
12631292
}
12641293

1265-
auto resolvers = _resolvers;
12661294
bool hasStitchedResolvers = false;
12671295

1268-
for (const auto& [name, resolver] : added->_resolvers)
1296+
if (added)
12691297
{
1270-
hasStitchedResolvers = resolvers.emplace(name, resolver).second || hasStitchedResolvers;
1298+
for (const auto& name : added->_typeNames)
1299+
{
1300+
typeNames.emplace(name);
1301+
}
1302+
1303+
for (const auto& [name, resolver] : added->_resolvers)
1304+
{
1305+
hasStitchedResolvers = resolvers.emplace(name, resolver).second || hasStitchedResolvers;
1306+
}
12711307
}
12721308

12731309
auto object = std::make_shared<Object>(std::move(typeNames), std::move(resolvers));
@@ -1779,64 +1815,81 @@ Request::~Request()
17791815
std::shared_ptr<const Request> Request::stitch(const std::shared_ptr<const Request>& added) const
17801816
{
17811817
TypeMap operations;
1818+
auto schema = _schema->StitchSchema(added->_schema);
1819+
std::shared_ptr<const Object> query;
17821820
auto itrOriginalQuery = _operations.find(strQuery);
17831821
auto itrAddedQuery = added->_operations.find(strQuery);
17841822

17851823
if (itrOriginalQuery != _operations.end() && itrOriginalQuery->second)
17861824
{
17871825
if (itrAddedQuery != added->_operations.end() && itrAddedQuery->second)
17881826
{
1789-
operations.emplace(strQuery,
1790-
itrOriginalQuery->second->StitchObject(itrAddedQuery->second));
1827+
query = itrOriginalQuery->second->StitchObject(itrAddedQuery->second, schema);
17911828
}
17921829
else
17931830
{
1794-
operations.emplace(strQuery, itrOriginalQuery->second);
1831+
query = itrOriginalQuery->second->StitchObject({}, schema);
17951832
}
17961833
}
17971834
else if (itrAddedQuery != added->_operations.end() && itrAddedQuery->second)
17981835
{
1799-
operations.emplace(strQuery, itrAddedQuery->second);
1836+
query = itrAddedQuery->second->StitchObject({}, schema);
18001837
}
18011838

1839+
if (query)
1840+
{
1841+
operations.emplace(strQuery, std::move(query));
1842+
}
1843+
1844+
std::shared_ptr<const Object> mutation;
18021845
auto itrOriginalMutation = _operations.find(strMutation);
18031846
auto itrAddedMutation = added->_operations.find(strMutation);
18041847

18051848
if (itrOriginalMutation != _operations.end() && itrOriginalMutation->second)
18061849
{
18071850
if (itrAddedMutation != added->_operations.end() && itrAddedMutation->second)
18081851
{
1809-
operations.emplace(strMutation,
1810-
itrOriginalMutation->second->StitchObject(itrAddedMutation->second));
1852+
mutation = itrOriginalMutation->second->StitchObject(itrAddedMutation->second);
18111853
}
18121854
else
18131855
{
1814-
operations.emplace(strMutation, itrOriginalMutation->second);
1856+
mutation = itrOriginalMutation->second;
18151857
}
18161858
}
18171859
else if (itrAddedMutation != added->_operations.end() && itrAddedMutation->second)
18181860
{
1819-
operations.emplace(strMutation, itrAddedMutation->second);
1861+
mutation = itrAddedMutation->second;
1862+
}
1863+
1864+
if (mutation)
1865+
{
1866+
operations.emplace(strMutation, std::move(mutation));
18201867
}
18211868

1869+
std::shared_ptr<const Object> subscription;
18221870
auto itrOriginalSubscription = _operations.find(strSubscription);
18231871
auto itrAddedSubscription = added->_operations.find(strSubscription);
18241872

18251873
if (itrOriginalSubscription != _operations.end() && itrOriginalSubscription->second)
18261874
{
18271875
if (itrAddedSubscription != added->_operations.end() && itrAddedSubscription->second)
18281876
{
1829-
operations.emplace(strSubscription,
1830-
itrOriginalSubscription->second->StitchObject(itrAddedSubscription->second));
1877+
subscription =
1878+
itrOriginalSubscription->second->StitchObject(itrAddedSubscription->second);
18311879
}
18321880
else
18331881
{
1834-
operations.emplace(strSubscription, itrOriginalSubscription->second);
1882+
subscription = itrOriginalSubscription->second;
18351883
}
18361884
}
18371885
else if (itrAddedSubscription != added->_operations.end() && itrAddedSubscription->second)
18381886
{
1839-
operations.emplace(strSubscription, itrAddedSubscription->second);
1887+
subscription = itrAddedSubscription->second;
1888+
}
1889+
1890+
if (subscription)
1891+
{
1892+
operations.emplace(strSubscription, std::move(subscription));
18401893
}
18411894

18421895
class StitchedRequest : public Request
@@ -1848,8 +1901,7 @@ std::shared_ptr<const Request> Request::stitch(const std::shared_ptr<const Reque
18481901
}
18491902
};
18501903

1851-
return std::make_shared<StitchedRequest>(std::move(operations),
1852-
_schema->StitchSchema(added->_schema));
1904+
return std::make_shared<StitchedRequest>(std::move(operations), std::move(schema));
18531905
}
18541906

18551907
std::list<schema_error> Request::validate(peg::ast& query) const

0 commit comments

Comments
 (0)