From f605261eb43150453b098a866ffe5468e51cb35d Mon Sep 17 00:00:00 2001 From: Bill Avery Date: Tue, 22 Oct 2024 15:52:14 -0700 Subject: [PATCH 1/2] fix: patch introspection resolvers in Object::StitchObject --- include/graphqlservice/GraphQLService.h | 3 +- src/GraphQLService.cpp | 68 +++++++++++++++++++------ 2 files changed, 55 insertions(+), 16 deletions(-) diff --git a/include/graphqlservice/GraphQLService.h b/include/graphqlservice/GraphQLService.h index 0d4f5621..b6c6eac2 100644 --- a/include/graphqlservice/GraphQLService.h +++ b/include/graphqlservice/GraphQLService.h @@ -830,7 +830,8 @@ class [[nodiscard("unnecessary construction")]] Object : public std::enable_shar GRAPHQLSERVICE_EXPORT virtual ~Object() = default; [[nodiscard("unnecessary call")]] GRAPHQLSERVICE_EXPORT std::shared_ptr StitchObject( - const std::shared_ptr& added) const; + const std::shared_ptr& added, + const std::shared_ptr& schema = {}) const; [[nodiscard("unnecessary call")]] GRAPHQLSERVICE_EXPORT AwaitableResolver resolve( const SelectionSetParams& selectionSetParams, const peg::ast_node& selection, diff --git a/src/GraphQLService.cpp b/src/GraphQLService.cpp index 59234dcb..3cf6b0fa 100644 --- a/src/GraphQLService.cpp +++ b/src/GraphQLService.cpp @@ -4,6 +4,10 @@ #include "graphqlservice/GraphQLService.h" #include "graphqlservice/internal/Grammar.h" +#include "graphqlservice/internal/Introspection.h" + +#include "graphqlservice/introspection/SchemaObject.h" +#include "graphqlservice/introspection/TypeObject.h" #include "Validation.h" @@ -267,7 +271,7 @@ void await_worker_queue::resumePending() // Default to immediate synchronous execution. await_async::await_async() : _pimpl { std::static_pointer_cast( - std::make_shared>(std::make_shared())) } + std::make_shared>(std::make_shared())) } { } @@ -275,9 +279,9 @@ await_async::await_async() await_async::await_async(std::launch launch) : _pimpl { ((launch & std::launch::async) == std::launch::async) ? std::static_pointer_cast(std::make_shared>( - std::make_shared())) + std::make_shared())) : std::static_pointer_cast(std::make_shared>( - std::make_shared())) } + std::make_shared())) } { } @@ -1253,21 +1257,50 @@ Object::Object(TypeNames&& typeNames, ResolverMap&& resolvers) noexcept { } -std::shared_ptr Object::StitchObject(const std::shared_ptr& added) const +std::shared_ptr Object::StitchObject(const std::shared_ptr& added, + const std::shared_ptr& schema /* = {} */) const { auto typeNames = _typeNames; + auto resolvers = _resolvers; - for (const auto& name : added->_typeNames) + if (schema && schema->supportsIntrospection()) { - typeNames.emplace(name); + resolvers.erase("__schema"sv); + resolvers.emplace("__schema"sv, [schema](ResolverParams&& params) { + return Result::convert( + std::static_pointer_cast(std::make_shared( + std::make_shared(schema))), + std::move(params)); + }); + + resolvers.erase("__type"sv); + resolvers.emplace("__type"sv, [schema](ResolverParams&& params) { + auto argName = ModifiedArgument::require("name", params.arguments); + const auto& baseType = schema->LookupType(argName); + std::shared_ptr result { baseType + ? std::make_shared( + std::make_shared(baseType)) + : nullptr }; + + return ModifiedResult::convert( + result, + std::move(params)); + }); } - auto resolvers = _resolvers; bool hasStitchedResolvers = false; - for (const auto& [name, resolver] : added->_resolvers) + if (added) { - hasStitchedResolvers = resolvers.emplace(name, resolver).second || hasStitchedResolvers; + for (const auto& name : added->_typeNames) + { + typeNames.emplace(name); + } + + for (const auto& [name, resolver] : added->_resolvers) + { + hasStitchedResolvers = resolvers.emplace(name, resolver).second || hasStitchedResolvers; + } } auto object = std::make_shared(std::move(typeNames), std::move(resolvers)); @@ -1779,6 +1812,8 @@ Request::~Request() std::shared_ptr Request::stitch(const std::shared_ptr& added) const { TypeMap operations; + auto schema = _schema->StitchSchema(added->_schema); + std::shared_ptr query; auto itrOriginalQuery = _operations.find(strQuery); auto itrAddedQuery = added->_operations.find(strQuery); @@ -1786,17 +1821,21 @@ std::shared_ptr Request::stitch(const std::shared_ptr_operations.end() && itrAddedQuery->second) { - operations.emplace(strQuery, - itrOriginalQuery->second->StitchObject(itrAddedQuery->second)); + query = itrOriginalQuery->second->StitchObject(itrAddedQuery->second, schema); } else { - operations.emplace(strQuery, itrOriginalQuery->second); + query = itrOriginalQuery->second->StitchObject({}, schema); } } else if (itrAddedQuery != added->_operations.end() && itrAddedQuery->second) { - operations.emplace(strQuery, itrAddedQuery->second); + query = itrAddedQuery->second->StitchObject({}, schema); + } + + if (query) + { + operations.emplace(strQuery, query); } auto itrOriginalMutation = _operations.find(strMutation); @@ -1848,8 +1887,7 @@ std::shared_ptr Request::stitch(const std::shared_ptr(std::move(operations), - _schema->StitchSchema(added->_schema)); + return std::make_shared(std::move(operations), std::move(schema)); } std::list Request::validate(peg::ast& query) const From 7662396290505144aa4ab0eb8954661c29fb8abb Mon Sep 17 00:00:00 2001 From: Bill Avery Date: Tue, 22 Oct 2024 16:18:05 -0700 Subject: [PATCH 2/2] fix: code cleanup to reduce duplication --- src/GraphQLService.cpp | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/src/GraphQLService.cpp b/src/GraphQLService.cpp index 3cf6b0fa..abc98739 100644 --- a/src/GraphQLService.cpp +++ b/src/GraphQLService.cpp @@ -1265,16 +1265,19 @@ std::shared_ptr Object::StitchObject(const std::shared_ptr if (schema && schema->supportsIntrospection()) { - resolvers.erase("__schema"sv); - resolvers.emplace("__schema"sv, [schema](ResolverParams&& params) { + constexpr auto schemaField = R"gql(__schema)gql"sv; + constexpr auto typeField = R"gql(__type)gql"sv; + + resolvers.erase(schemaField); + resolvers.emplace(schemaField, [schema](ResolverParams&& params) { return Result::convert( std::static_pointer_cast(std::make_shared( std::make_shared(schema))), std::move(params)); }); - resolvers.erase("__type"sv); - resolvers.emplace("__type"sv, [schema](ResolverParams&& params) { + resolvers.erase(typeField); + resolvers.emplace(typeField, [schema](ResolverParams&& params) { auto argName = ModifiedArgument::require("name", params.arguments); const auto& baseType = schema->LookupType(argName); std::shared_ptr result { baseType @@ -1813,7 +1816,7 @@ std::shared_ptr Request::stitch(const std::shared_ptrStitchSchema(added->_schema); - std::shared_ptr query; + std::shared_ptr query; auto itrOriginalQuery = _operations.find(strQuery); auto itrAddedQuery = added->_operations.find(strQuery); @@ -1835,9 +1838,10 @@ std::shared_ptr Request::stitch(const std::shared_ptr mutation; auto itrOriginalMutation = _operations.find(strMutation); auto itrAddedMutation = added->_operations.find(strMutation); @@ -1845,19 +1849,24 @@ std::shared_ptr Request::stitch(const std::shared_ptr_operations.end() && itrAddedMutation->second) { - operations.emplace(strMutation, - itrOriginalMutation->second->StitchObject(itrAddedMutation->second)); + mutation = itrOriginalMutation->second->StitchObject(itrAddedMutation->second); } else { - operations.emplace(strMutation, itrOriginalMutation->second); + mutation = itrOriginalMutation->second; } } else if (itrAddedMutation != added->_operations.end() && itrAddedMutation->second) { - operations.emplace(strMutation, itrAddedMutation->second); + mutation = itrAddedMutation->second; + } + + if (mutation) + { + operations.emplace(strMutation, std::move(mutation)); } + std::shared_ptr subscription; auto itrOriginalSubscription = _operations.find(strSubscription); auto itrAddedSubscription = added->_operations.find(strSubscription); @@ -1865,17 +1874,22 @@ std::shared_ptr Request::stitch(const std::shared_ptr_operations.end() && itrAddedSubscription->second) { - operations.emplace(strSubscription, - itrOriginalSubscription->second->StitchObject(itrAddedSubscription->second)); + subscription = + itrOriginalSubscription->second->StitchObject(itrAddedSubscription->second); } else { - operations.emplace(strSubscription, itrOriginalSubscription->second); + subscription = itrOriginalSubscription->second; } } else if (itrAddedSubscription != added->_operations.end() && itrAddedSubscription->second) { - operations.emplace(strSubscription, itrAddedSubscription->second); + subscription = itrAddedSubscription->second; + } + + if (subscription) + { + operations.emplace(strSubscription, std::move(subscription)); } class StitchedRequest : public Request