4
4
#include " graphqlservice/GraphQLService.h"
5
5
6
6
#include " graphqlservice/internal/Grammar.h"
7
+ #include " graphqlservice/internal/Introspection.h"
8
+
9
+ #include " graphqlservice/introspection/SchemaObject.h"
10
+ #include " graphqlservice/introspection/TypeObject.h"
7
11
8
12
#include " Validation.h"
9
13
@@ -267,17 +271,17 @@ void await_worker_queue::resumePending()
267
271
// Default to immediate synchronous execution.
268
272
await_async::await_async ()
269
273
: _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>())) }
271
275
{
272
276
}
273
277
274
278
// Implicitly convert a std::launch parameter used with std::async to an awaitable.
275
279
await_async::await_async (std::launch launch)
276
280
: _pimpl { ((launch & std::launch::async) == std::launch::async)
277
281
? 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>()))
279
283
: 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>())) }
281
285
{
282
286
}
283
287
@@ -1253,21 +1257,53 @@ Object::Object(TypeNames&& typeNames, ResolverMap&& resolvers) noexcept
1253
1257
{
1254
1258
}
1255
1259
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
1257
1262
{
1258
1263
auto typeNames = _typeNames;
1264
+ auto resolvers = _resolvers;
1259
1265
1260
- for ( const auto & name : added-> _typeNames )
1266
+ if (schema && schema-> supportsIntrospection () )
1261
1267
{
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
+ });
1263
1292
}
1264
1293
1265
- auto resolvers = _resolvers;
1266
1294
bool hasStitchedResolvers = false ;
1267
1295
1268
- for ( const auto & [name, resolver] : added-> _resolvers )
1296
+ if ( added)
1269
1297
{
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
+ }
1271
1307
}
1272
1308
1273
1309
auto object = std::make_shared<Object>(std::move (typeNames), std::move (resolvers));
@@ -1779,64 +1815,81 @@ Request::~Request()
1779
1815
std::shared_ptr<const Request> Request::stitch (const std::shared_ptr<const Request>& added) const
1780
1816
{
1781
1817
TypeMap operations;
1818
+ auto schema = _schema->StitchSchema (added->_schema );
1819
+ std::shared_ptr<const Object> query;
1782
1820
auto itrOriginalQuery = _operations.find (strQuery);
1783
1821
auto itrAddedQuery = added->_operations .find (strQuery);
1784
1822
1785
1823
if (itrOriginalQuery != _operations.end () && itrOriginalQuery->second )
1786
1824
{
1787
1825
if (itrAddedQuery != added->_operations .end () && itrAddedQuery->second )
1788
1826
{
1789
- operations.emplace (strQuery,
1790
- itrOriginalQuery->second ->StitchObject (itrAddedQuery->second ));
1827
+ query = itrOriginalQuery->second ->StitchObject (itrAddedQuery->second , schema);
1791
1828
}
1792
1829
else
1793
1830
{
1794
- operations. emplace (strQuery, itrOriginalQuery->second );
1831
+ query = itrOriginalQuery->second -> StitchObject ({}, schema );
1795
1832
}
1796
1833
}
1797
1834
else if (itrAddedQuery != added->_operations .end () && itrAddedQuery->second )
1798
1835
{
1799
- operations. emplace (strQuery, itrAddedQuery->second );
1836
+ query = itrAddedQuery->second -> StitchObject ({}, schema );
1800
1837
}
1801
1838
1839
+ if (query)
1840
+ {
1841
+ operations.emplace (strQuery, std::move (query));
1842
+ }
1843
+
1844
+ std::shared_ptr<const Object> mutation;
1802
1845
auto itrOriginalMutation = _operations.find (strMutation);
1803
1846
auto itrAddedMutation = added->_operations .find (strMutation);
1804
1847
1805
1848
if (itrOriginalMutation != _operations.end () && itrOriginalMutation->second )
1806
1849
{
1807
1850
if (itrAddedMutation != added->_operations .end () && itrAddedMutation->second )
1808
1851
{
1809
- operations.emplace (strMutation,
1810
- itrOriginalMutation->second ->StitchObject (itrAddedMutation->second ));
1852
+ mutation = itrOriginalMutation->second ->StitchObject (itrAddedMutation->second );
1811
1853
}
1812
1854
else
1813
1855
{
1814
- operations. emplace (strMutation, itrOriginalMutation->second ) ;
1856
+ mutation = itrOriginalMutation->second ;
1815
1857
}
1816
1858
}
1817
1859
else if (itrAddedMutation != added->_operations .end () && itrAddedMutation->second )
1818
1860
{
1819
- operations.emplace (strMutation, itrAddedMutation->second );
1861
+ mutation = itrAddedMutation->second ;
1862
+ }
1863
+
1864
+ if (mutation)
1865
+ {
1866
+ operations.emplace (strMutation, std::move (mutation));
1820
1867
}
1821
1868
1869
+ std::shared_ptr<const Object> subscription;
1822
1870
auto itrOriginalSubscription = _operations.find (strSubscription);
1823
1871
auto itrAddedSubscription = added->_operations .find (strSubscription);
1824
1872
1825
1873
if (itrOriginalSubscription != _operations.end () && itrOriginalSubscription->second )
1826
1874
{
1827
1875
if (itrAddedSubscription != added->_operations .end () && itrAddedSubscription->second )
1828
1876
{
1829
- operations. emplace (strSubscription,
1830
- itrOriginalSubscription->second ->StitchObject (itrAddedSubscription->second )) ;
1877
+ subscription =
1878
+ itrOriginalSubscription->second ->StitchObject (itrAddedSubscription->second );
1831
1879
}
1832
1880
else
1833
1881
{
1834
- operations. emplace (strSubscription, itrOriginalSubscription->second ) ;
1882
+ subscription = itrOriginalSubscription->second ;
1835
1883
}
1836
1884
}
1837
1885
else if (itrAddedSubscription != added->_operations .end () && itrAddedSubscription->second )
1838
1886
{
1839
- operations.emplace (strSubscription, itrAddedSubscription->second );
1887
+ subscription = itrAddedSubscription->second ;
1888
+ }
1889
+
1890
+ if (subscription)
1891
+ {
1892
+ operations.emplace (strSubscription, std::move (subscription));
1840
1893
}
1841
1894
1842
1895
class StitchedRequest : public Request
@@ -1848,8 +1901,7 @@ std::shared_ptr<const Request> Request::stitch(const std::shared_ptr<const Reque
1848
1901
}
1849
1902
};
1850
1903
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));
1853
1905
}
1854
1906
1855
1907
std::list<schema_error> Request::validate (peg::ast& query) const
0 commit comments