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.
268272await_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.
275279await_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()
17791815std::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
18551907std::list<schema_error> Request::validate (peg::ast& query) const
0 commit comments