diff --git a/cmake/cppgraphqlgen-update-schema-files.cmake b/cmake/cppgraphqlgen-update-schema-files.cmake index 8955f6fd..44a840c2 100644 --- a/cmake/cppgraphqlgen-update-schema-files.cmake +++ b/cmake/cppgraphqlgen-update-schema-files.cmake @@ -52,7 +52,10 @@ foreach(OLD_FILE ${OLD_FILES}) file(REMOVE "${SCHEMA_SOURCE_DIR}/${OLD_FILE}") elseif(NOT OLD_FILE STREQUAL "${SCHEMA_PREFIX}Schema.h" AND NOT OLD_FILE STREQUAL "${SCHEMA_PREFIX}Schema.ixx" AND - NOT OLD_FILE STREQUAL "${SCHEMA_PREFIX}Schema.cpp") + NOT OLD_FILE STREQUAL "${SCHEMA_PREFIX}Schema.cpp" AND + NOT OLD_FILE STREQUAL "${SCHEMA_PREFIX}SharedTypes.h" AND + NOT OLD_FILE STREQUAL "${SCHEMA_PREFIX}SharedTypes.ixx" AND + NOT OLD_FILE STREQUAL "${SCHEMA_PREFIX}SharedTypes.cpp") message(WARNING "Unexpected file in ${SCHEMA_TARGET} GraphQL schema sources: ${OLD_FILE}") endif() endif() diff --git a/include/SchemaGenerator.h b/include/SchemaGenerator.h index 82c1a2b7..561dc01c 100644 --- a/include/SchemaGenerator.h +++ b/include/SchemaGenerator.h @@ -38,12 +38,17 @@ class [[nodiscard("unnecessary construction")]] Generator private: [[nodiscard("unnecessary memory copy")]] std::string getHeaderDir() const noexcept; [[nodiscard("unnecessary memory copy")]] std::string getSourceDir() const noexcept; - [[nodiscard("unnecessary memory copy")]] std::string getHeaderPath() const noexcept; - [[nodiscard("unnecessary memory copy")]] std::string getModulePath() const noexcept; - [[nodiscard("unnecessary memory copy")]] std::string getSourcePath() const noexcept; - - [[nodiscard("unnecessary call")]] bool outputHeader() const noexcept; - [[nodiscard("unnecessary call")]] bool outputModule() const noexcept; + [[nodiscard("unnecessary memory copy")]] std::string getSchemaHeaderPath() const noexcept; + [[nodiscard("unnecessary memory copy")]] std::string getSchemaModulePath() const noexcept; + [[nodiscard("unnecessary memory copy")]] std::string getSchemaSourcePath() const noexcept; + [[nodiscard("unnecessary memory copy")]] std::string getSharedTypesHeaderPath() const noexcept; + [[nodiscard("unnecessary memory copy")]] std::string getSharedTypesModulePath() const noexcept; + [[nodiscard("unnecessary memory copy")]] std::string getSharedTypesSourcePath() const noexcept; + + [[nodiscard("unnecessary call")]] bool outputSchemaHeader() const noexcept; + [[nodiscard("unnecessary call")]] bool outputSchemaModule() const noexcept; + [[nodiscard("unnecessary call")]] bool outputSharedTypesHeader() const noexcept; + [[nodiscard("unnecessary call")]] bool outputSharedTypesModule() const noexcept; void outputInterfaceDeclaration(std::ostream& headerFile, std::string_view cppType) const; void outputObjectModule( std::ostream& moduleFile, std::string_view objectNamespace, std::string_view cppType) const; @@ -58,7 +63,8 @@ class [[nodiscard("unnecessary construction")]] Generator [[nodiscard("unnecessary memory copy")]] std::string getResolverDeclaration( const OutputField& outputField) const noexcept; - [[nodiscard("unnecessary call")]] bool outputSource() const noexcept; + [[nodiscard("unnecessary call")]] bool outputSchemaSource() const noexcept; + [[nodiscard("unnecessary call")]] bool outputSharedTypesSource() const noexcept; void outputInterfaceImplementation(std::ostream& sourceFile, std::string_view cppType) const; void outputInterfaceIntrospection( std::ostream& sourceFile, const InterfaceType& interfaceType) const; @@ -94,9 +100,12 @@ class [[nodiscard("unnecessary construction")]] Generator const std::string _headerDir; const std::string _moduleDir; const std::string _sourceDir; - const std::string _headerPath; - const std::string _modulePath; - const std::string _sourcePath; + const std::string _schemaHeaderPath; + const std::string _schemaModulePath; + const std::string _schemaSourcePath; + const std::string _sharedTypesHeaderPath; + const std::string _sharedTypesModulePath; + const std::string _sharedTypesSourcePath; }; } // namespace graphql::generator::schema diff --git a/include/graphqlservice/introspection/IntrospectionSchema.h b/include/graphqlservice/introspection/IntrospectionSchema.h index b754e4ad..b39fe13f 100644 --- a/include/graphqlservice/introspection/IntrospectionSchema.h +++ b/include/graphqlservice/introspection/IntrospectionSchema.h @@ -11,9 +11,12 @@ #include "graphqlservice/GraphQLResponse.h" #include "graphqlservice/GraphQLService.h" +#include "graphqlservice/internal/DllExports.h" #include "graphqlservice/internal/Version.h" #include "graphqlservice/internal/Schema.h" +#include "IntrospectionSharedTypes.h" + #include #include #include @@ -23,130 +26,7 @@ static_assert(graphql::internal::MajorVersion == 5, "regenerate with schemagen: major version mismatch"); static_assert(graphql::internal::MinorVersion == 0, "regenerate with schemagen: minor version mismatch"); -namespace graphql { -namespace introspection { - -enum class TypeKind -{ - SCALAR, - OBJECT, - INTERFACE, - UNION, - ENUM, - INPUT_OBJECT, - LIST, - NON_NULL -}; - -[[nodiscard("unnecessary call")]] constexpr auto getTypeKindNames() noexcept -{ - using namespace std::literals; - - return std::array { - R"gql(SCALAR)gql"sv, - R"gql(OBJECT)gql"sv, - R"gql(INTERFACE)gql"sv, - R"gql(UNION)gql"sv, - R"gql(ENUM)gql"sv, - R"gql(INPUT_OBJECT)gql"sv, - R"gql(LIST)gql"sv, - R"gql(NON_NULL)gql"sv - }; -} - -[[nodiscard("unnecessary call")]] constexpr auto getTypeKindValues() noexcept -{ - using namespace std::literals; - - return std::array, 8> { - std::make_pair(R"gql(ENUM)gql"sv, TypeKind::ENUM), - std::make_pair(R"gql(LIST)gql"sv, TypeKind::LIST), - std::make_pair(R"gql(UNION)gql"sv, TypeKind::UNION), - std::make_pair(R"gql(OBJECT)gql"sv, TypeKind::OBJECT), - std::make_pair(R"gql(SCALAR)gql"sv, TypeKind::SCALAR), - std::make_pair(R"gql(NON_NULL)gql"sv, TypeKind::NON_NULL), - std::make_pair(R"gql(INTERFACE)gql"sv, TypeKind::INTERFACE), - std::make_pair(R"gql(INPUT_OBJECT)gql"sv, TypeKind::INPUT_OBJECT) - }; -} - -enum class DirectiveLocation -{ - QUERY, - MUTATION, - SUBSCRIPTION, - FIELD, - FRAGMENT_DEFINITION, - FRAGMENT_SPREAD, - INLINE_FRAGMENT, - VARIABLE_DEFINITION, - SCHEMA, - SCALAR, - OBJECT, - FIELD_DEFINITION, - ARGUMENT_DEFINITION, - INTERFACE, - UNION, - ENUM, - ENUM_VALUE, - INPUT_OBJECT, - INPUT_FIELD_DEFINITION -}; - -[[nodiscard("unnecessary call")]] constexpr auto getDirectiveLocationNames() noexcept -{ - using namespace std::literals; - - return std::array { - R"gql(QUERY)gql"sv, - R"gql(MUTATION)gql"sv, - R"gql(SUBSCRIPTION)gql"sv, - R"gql(FIELD)gql"sv, - R"gql(FRAGMENT_DEFINITION)gql"sv, - R"gql(FRAGMENT_SPREAD)gql"sv, - R"gql(INLINE_FRAGMENT)gql"sv, - R"gql(VARIABLE_DEFINITION)gql"sv, - R"gql(SCHEMA)gql"sv, - R"gql(SCALAR)gql"sv, - R"gql(OBJECT)gql"sv, - R"gql(FIELD_DEFINITION)gql"sv, - R"gql(ARGUMENT_DEFINITION)gql"sv, - R"gql(INTERFACE)gql"sv, - R"gql(UNION)gql"sv, - R"gql(ENUM)gql"sv, - R"gql(ENUM_VALUE)gql"sv, - R"gql(INPUT_OBJECT)gql"sv, - R"gql(INPUT_FIELD_DEFINITION)gql"sv - }; -} - -[[nodiscard("unnecessary call")]] constexpr auto getDirectiveLocationValues() noexcept -{ - using namespace std::literals; - - return std::array, 19> { - std::make_pair(R"gql(ENUM)gql"sv, DirectiveLocation::ENUM), - std::make_pair(R"gql(FIELD)gql"sv, DirectiveLocation::FIELD), - std::make_pair(R"gql(QUERY)gql"sv, DirectiveLocation::QUERY), - std::make_pair(R"gql(UNION)gql"sv, DirectiveLocation::UNION), - std::make_pair(R"gql(OBJECT)gql"sv, DirectiveLocation::OBJECT), - std::make_pair(R"gql(SCALAR)gql"sv, DirectiveLocation::SCALAR), - std::make_pair(R"gql(SCHEMA)gql"sv, DirectiveLocation::SCHEMA), - std::make_pair(R"gql(MUTATION)gql"sv, DirectiveLocation::MUTATION), - std::make_pair(R"gql(INTERFACE)gql"sv, DirectiveLocation::INTERFACE), - std::make_pair(R"gql(ENUM_VALUE)gql"sv, DirectiveLocation::ENUM_VALUE), - std::make_pair(R"gql(INPUT_OBJECT)gql"sv, DirectiveLocation::INPUT_OBJECT), - std::make_pair(R"gql(SUBSCRIPTION)gql"sv, DirectiveLocation::SUBSCRIPTION), - std::make_pair(R"gql(FRAGMENT_SPREAD)gql"sv, DirectiveLocation::FRAGMENT_SPREAD), - std::make_pair(R"gql(INLINE_FRAGMENT)gql"sv, DirectiveLocation::INLINE_FRAGMENT), - std::make_pair(R"gql(FIELD_DEFINITION)gql"sv, DirectiveLocation::FIELD_DEFINITION), - std::make_pair(R"gql(ARGUMENT_DEFINITION)gql"sv, DirectiveLocation::ARGUMENT_DEFINITION), - std::make_pair(R"gql(FRAGMENT_DEFINITION)gql"sv, DirectiveLocation::FRAGMENT_DEFINITION), - std::make_pair(R"gql(VARIABLE_DEFINITION)gql"sv, DirectiveLocation::VARIABLE_DEFINITION), - std::make_pair(R"gql(INPUT_FIELD_DEFINITION)gql"sv, DirectiveLocation::INPUT_FIELD_DEFINITION) - }; -} - +namespace graphql::introspection { class Schema; class Type; class Field; @@ -174,33 +54,6 @@ void AddDirectiveDetails(const std::shared_ptr& typeDirectiv GRAPHQLSERVICE_EXPORT void AddTypesToSchema(const std::shared_ptr& schema); -} // namespace introspection - -namespace service { - -#ifdef GRAPHQL_DLLEXPORTS -// Export all of the built-in converters -template <> -GRAPHQLSERVICE_EXPORT introspection::TypeKind Argument::convert( - const response::Value& value); -template <> -GRAPHQLSERVICE_EXPORT AwaitableResolver Result::convert( - AwaitableScalar result, ResolverParams&& params); -template <> -GRAPHQLSERVICE_EXPORT void Result::validateScalar( - const response::Value& value); -template <> -GRAPHQLSERVICE_EXPORT introspection::DirectiveLocation Argument::convert( - const response::Value& value); -template <> -GRAPHQLSERVICE_EXPORT AwaitableResolver Result::convert( - AwaitableScalar result, ResolverParams&& params); -template <> -GRAPHQLSERVICE_EXPORT void Result::validateScalar( - const response::Value& value); -#endif // GRAPHQL_DLLEXPORTS - -} // namespace service -} // namespace graphql +} // namespace graphql::introspection #endif // INTROSPECTIONSCHEMA_H diff --git a/include/graphqlservice/introspection/IntrospectionSchema.ixx b/include/graphqlservice/introspection/IntrospectionSchema.ixx index 45f3f14a..8ce51120 100644 --- a/include/graphqlservice/introspection/IntrospectionSchema.ixx +++ b/include/graphqlservice/introspection/IntrospectionSchema.ixx @@ -9,6 +9,8 @@ module; export module GraphQL.Introspection.IntrospectionSchema; +export import GraphQL.Introspection.IntrospectionSharedTypes; + export import GraphQL.Introspection.SchemaObject; export import GraphQL.Introspection.TypeObject; export import GraphQL.Introspection.FieldObject; @@ -18,14 +20,6 @@ export import GraphQL.Introspection.DirectiveObject; export namespace graphql::introspection { -using introspection::TypeKind; -using introspection::getTypeKindNames; -using introspection::getTypeKindValues; - -using introspection::DirectiveLocation; -using introspection::getDirectiveLocationNames; -using introspection::getDirectiveLocationValues; - using introspection::AddSchemaDetails; using introspection::AddTypeDetails; using introspection::AddFieldDetails; diff --git a/include/graphqlservice/introspection/IntrospectionSharedTypes.h b/include/graphqlservice/introspection/IntrospectionSharedTypes.h new file mode 100644 index 00000000..9e1d5acb --- /dev/null +++ b/include/graphqlservice/introspection/IntrospectionSharedTypes.h @@ -0,0 +1,180 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// WARNING! Do not edit this file manually, your changes will be overwritten. + +#pragma once + +#ifndef INTROSPECTIONSHAREDTYPES_H +#define INTROSPECTIONSHAREDTYPES_H + +#include "graphqlservice/GraphQLResponse.h" + +#include "graphqlservice/internal/DllExports.h" +#include "graphqlservice/internal/Version.h" + +#include +#include +#include +#include +#include +#include + +// Check if the library version is compatible with schemagen 5.0.0 +static_assert(graphql::internal::MajorVersion == 5, "regenerate with schemagen: major version mismatch"); +static_assert(graphql::internal::MinorVersion == 0, "regenerate with schemagen: minor version mismatch"); + +namespace graphql { +namespace introspection { + +enum class TypeKind +{ + SCALAR, + OBJECT, + INTERFACE, + UNION, + ENUM, + INPUT_OBJECT, + LIST, + NON_NULL +}; + +[[nodiscard("unnecessary call")]] constexpr auto getTypeKindNames() noexcept +{ + using namespace std::literals; + + return std::array { + R"gql(SCALAR)gql"sv, + R"gql(OBJECT)gql"sv, + R"gql(INTERFACE)gql"sv, + R"gql(UNION)gql"sv, + R"gql(ENUM)gql"sv, + R"gql(INPUT_OBJECT)gql"sv, + R"gql(LIST)gql"sv, + R"gql(NON_NULL)gql"sv + }; +} + +[[nodiscard("unnecessary call")]] constexpr auto getTypeKindValues() noexcept +{ + using namespace std::literals; + + return std::array, 8> { + std::make_pair(R"gql(ENUM)gql"sv, TypeKind::ENUM), + std::make_pair(R"gql(LIST)gql"sv, TypeKind::LIST), + std::make_pair(R"gql(UNION)gql"sv, TypeKind::UNION), + std::make_pair(R"gql(OBJECT)gql"sv, TypeKind::OBJECT), + std::make_pair(R"gql(SCALAR)gql"sv, TypeKind::SCALAR), + std::make_pair(R"gql(NON_NULL)gql"sv, TypeKind::NON_NULL), + std::make_pair(R"gql(INTERFACE)gql"sv, TypeKind::INTERFACE), + std::make_pair(R"gql(INPUT_OBJECT)gql"sv, TypeKind::INPUT_OBJECT) + }; +} + +enum class DirectiveLocation +{ + QUERY, + MUTATION, + SUBSCRIPTION, + FIELD, + FRAGMENT_DEFINITION, + FRAGMENT_SPREAD, + INLINE_FRAGMENT, + VARIABLE_DEFINITION, + SCHEMA, + SCALAR, + OBJECT, + FIELD_DEFINITION, + ARGUMENT_DEFINITION, + INTERFACE, + UNION, + ENUM, + ENUM_VALUE, + INPUT_OBJECT, + INPUT_FIELD_DEFINITION +}; + +[[nodiscard("unnecessary call")]] constexpr auto getDirectiveLocationNames() noexcept +{ + using namespace std::literals; + + return std::array { + R"gql(QUERY)gql"sv, + R"gql(MUTATION)gql"sv, + R"gql(SUBSCRIPTION)gql"sv, + R"gql(FIELD)gql"sv, + R"gql(FRAGMENT_DEFINITION)gql"sv, + R"gql(FRAGMENT_SPREAD)gql"sv, + R"gql(INLINE_FRAGMENT)gql"sv, + R"gql(VARIABLE_DEFINITION)gql"sv, + R"gql(SCHEMA)gql"sv, + R"gql(SCALAR)gql"sv, + R"gql(OBJECT)gql"sv, + R"gql(FIELD_DEFINITION)gql"sv, + R"gql(ARGUMENT_DEFINITION)gql"sv, + R"gql(INTERFACE)gql"sv, + R"gql(UNION)gql"sv, + R"gql(ENUM)gql"sv, + R"gql(ENUM_VALUE)gql"sv, + R"gql(INPUT_OBJECT)gql"sv, + R"gql(INPUT_FIELD_DEFINITION)gql"sv + }; +} + +[[nodiscard("unnecessary call")]] constexpr auto getDirectiveLocationValues() noexcept +{ + using namespace std::literals; + + return std::array, 19> { + std::make_pair(R"gql(ENUM)gql"sv, DirectiveLocation::ENUM), + std::make_pair(R"gql(FIELD)gql"sv, DirectiveLocation::FIELD), + std::make_pair(R"gql(QUERY)gql"sv, DirectiveLocation::QUERY), + std::make_pair(R"gql(UNION)gql"sv, DirectiveLocation::UNION), + std::make_pair(R"gql(OBJECT)gql"sv, DirectiveLocation::OBJECT), + std::make_pair(R"gql(SCALAR)gql"sv, DirectiveLocation::SCALAR), + std::make_pair(R"gql(SCHEMA)gql"sv, DirectiveLocation::SCHEMA), + std::make_pair(R"gql(MUTATION)gql"sv, DirectiveLocation::MUTATION), + std::make_pair(R"gql(INTERFACE)gql"sv, DirectiveLocation::INTERFACE), + std::make_pair(R"gql(ENUM_VALUE)gql"sv, DirectiveLocation::ENUM_VALUE), + std::make_pair(R"gql(INPUT_OBJECT)gql"sv, DirectiveLocation::INPUT_OBJECT), + std::make_pair(R"gql(SUBSCRIPTION)gql"sv, DirectiveLocation::SUBSCRIPTION), + std::make_pair(R"gql(FRAGMENT_SPREAD)gql"sv, DirectiveLocation::FRAGMENT_SPREAD), + std::make_pair(R"gql(INLINE_FRAGMENT)gql"sv, DirectiveLocation::INLINE_FRAGMENT), + std::make_pair(R"gql(FIELD_DEFINITION)gql"sv, DirectiveLocation::FIELD_DEFINITION), + std::make_pair(R"gql(ARGUMENT_DEFINITION)gql"sv, DirectiveLocation::ARGUMENT_DEFINITION), + std::make_pair(R"gql(FRAGMENT_DEFINITION)gql"sv, DirectiveLocation::FRAGMENT_DEFINITION), + std::make_pair(R"gql(VARIABLE_DEFINITION)gql"sv, DirectiveLocation::VARIABLE_DEFINITION), + std::make_pair(R"gql(INPUT_FIELD_DEFINITION)gql"sv, DirectiveLocation::INPUT_FIELD_DEFINITION) + }; +} + +} // namespace introspection + +namespace service { + +#ifdef GRAPHQL_DLLEXPORTS +// Export all of the built-in converters +template <> +GRAPHQLSERVICE_EXPORT introspection::TypeKind Argument::convert( + const response::Value& value); +template <> +GRAPHQLSERVICE_EXPORT AwaitableResolver Result::convert( + AwaitableScalar result, ResolverParams&& params); +template <> +GRAPHQLSERVICE_EXPORT void Result::validateScalar( + const response::Value& value); +template <> +GRAPHQLSERVICE_EXPORT introspection::DirectiveLocation Argument::convert( + const response::Value& value); +template <> +GRAPHQLSERVICE_EXPORT AwaitableResolver Result::convert( + AwaitableScalar result, ResolverParams&& params); +template <> +GRAPHQLSERVICE_EXPORT void Result::validateScalar( + const response::Value& value); +#endif // GRAPHQL_DLLEXPORTS + +} // namespace service +} // namespace graphql + +#endif // INTROSPECTIONSHAREDTYPES_H diff --git a/include/graphqlservice/introspection/IntrospectionSharedTypes.ixx b/include/graphqlservice/introspection/IntrospectionSharedTypes.ixx new file mode 100644 index 00000000..60538148 --- /dev/null +++ b/include/graphqlservice/introspection/IntrospectionSharedTypes.ixx @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// WARNING! Do not edit this file manually, your changes will be overwritten. + +module; + +#include "IntrospectionSharedTypes.h" + +export module GraphQL.Introspection.IntrospectionSharedTypes; + +export namespace graphql::introspection { + +using introspection::TypeKind; +using introspection::getTypeKindNames; +using introspection::getTypeKindValues; + +using introspection::DirectiveLocation; +using introspection::getDirectiveLocationNames; +using introspection::getDirectiveLocationValues; + +} // namespace graphql::introspection diff --git a/samples/client/benchmark/TodayClient.h b/samples/client/benchmark/TodayClient.h index d0f74413..453685fe 100644 --- a/samples/client/benchmark/TodayClient.h +++ b/samples/client/benchmark/TodayClient.h @@ -14,7 +14,7 @@ #include "graphqlservice/internal/Version.h" -#include "TodaySchema.h" +#include "TodaySharedTypes.h" #include #include diff --git a/samples/learn/schema/StarWarsSchema.cpp b/samples/learn/schema/StarWarsSchema.cpp index 90d252e1..6e093b32 100644 --- a/samples/learn/schema/StarWarsSchema.cpp +++ b/samples/learn/schema/StarWarsSchema.cpp @@ -22,129 +22,7 @@ using namespace std::literals; -namespace graphql { -namespace service { - -static const auto s_namesEpisode = learn::getEpisodeNames(); -static const auto s_valuesEpisode = learn::getEpisodeValues(); - -template <> -learn::Episode Argument::convert(const response::Value& value) -{ - if (!value.maybe_enum()) - { - throw service::schema_exception { { R"ex(not a valid Episode value)ex" } }; - } - - const auto result = internal::sorted_map_lookup( - s_valuesEpisode, - std::string_view { value.get() }); - - if (!result) - { - throw service::schema_exception { { R"ex(not a valid Episode value)ex" } }; - } - - return *result; -} - -template <> -service::AwaitableResolver Result::convert(service::AwaitableScalar result, ResolverParams&& params) -{ - return ModifiedResult::resolve(std::move(result), std::move(params), - [](learn::Episode value, const ResolverParams&) - { - response::Value resolvedResult(response::Type::EnumValue); - - resolvedResult.set(std::string { s_namesEpisode[static_cast(value)] }); - - return resolvedResult; - }); -} - -template <> -void Result::validateScalar(const response::Value& value) -{ - if (!value.maybe_enum()) - { - throw service::schema_exception { { R"ex(not a valid Episode value)ex" } }; - } - - const auto [itr, itrEnd] = internal::sorted_map_equal_range( - s_valuesEpisode.begin(), - s_valuesEpisode.end(), - std::string_view { value.get() }); - - if (itr == itrEnd) - { - throw service::schema_exception { { R"ex(not a valid Episode value)ex" } }; - } -} - -template <> -learn::ReviewInput Argument::convert(const response::Value& value) -{ - auto valueStars = service::ModifiedArgument::require("stars", value); - auto valueCommentary = service::ModifiedArgument::require("commentary", value); - - return learn::ReviewInput { - valueStars, - std::move(valueCommentary) - }; -} - -} // namespace service - -namespace learn { - -ReviewInput::ReviewInput() noexcept - : stars {} - , commentary {} -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -ReviewInput::ReviewInput( - int starsArg, - std::optional commentaryArg) noexcept - : stars { std::move(starsArg) } - , commentary { std::move(commentaryArg) } -{ -} - -ReviewInput::ReviewInput(const ReviewInput& other) - : stars { service::ModifiedArgument::duplicate(other.stars) } - , commentary { service::ModifiedArgument::duplicate(other.commentary) } -{ -} - -ReviewInput::ReviewInput(ReviewInput&& other) noexcept - : stars { std::move(other.stars) } - , commentary { std::move(other.commentary) } -{ -} - -ReviewInput::~ReviewInput() -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -ReviewInput& ReviewInput::operator=(const ReviewInput& other) -{ - ReviewInput value { other }; - - std::swap(*this, value); - - return *this; -} - -ReviewInput& ReviewInput::operator=(ReviewInput&& other) noexcept -{ - stars = std::move(other.stars); - commentary = std::move(other.commentary); - - return *this; -} +namespace graphql::learn { Operations::Operations(std::shared_ptr query, std::shared_ptr mutation, std::shared_ptr subscription) : service::Request({ @@ -179,10 +57,11 @@ void AddTypesToSchema(const std::shared_ptr& schema) auto typeSubscription = schema::ObjectType::Make(R"gql(Subscription)gql"sv, R"md()md"sv); schema->AddType(R"gql(Subscription)gql"sv, typeSubscription); + static const auto s_namesEpisode = getEpisodeNames(); typeEpisode->AddEnumValues({ - { service::s_namesEpisode[static_cast(learn::Episode::NEW_HOPE)], R"md()md"sv, std::nullopt }, - { service::s_namesEpisode[static_cast(learn::Episode::EMPIRE)], R"md()md"sv, std::nullopt }, - { service::s_namesEpisode[static_cast(learn::Episode::JEDI)], R"md()md"sv, std::nullopt } + { s_namesEpisode[static_cast(learn::Episode::NEW_HOPE)], R"md()md"sv, std::nullopt }, + { s_namesEpisode[static_cast(learn::Episode::EMPIRE)], R"md()md"sv, std::nullopt }, + { s_namesEpisode[static_cast(learn::Episode::JEDI)], R"md()md"sv, std::nullopt } }); typeReviewInput->AddInputValues({ @@ -220,5 +99,4 @@ std::shared_ptr GetSchema() return schema; } -} // namespace learn -} // namespace graphql +} // namespace graphql::learn diff --git a/samples/learn/schema/StarWarsSchema.h b/samples/learn/schema/StarWarsSchema.h index 11950217..9529c7ec 100644 --- a/samples/learn/schema/StarWarsSchema.h +++ b/samples/learn/schema/StarWarsSchema.h @@ -14,6 +14,8 @@ #include "graphqlservice/internal/Version.h" #include "graphqlservice/internal/Schema.h" +#include "StarWarsSharedTypes.h" + #include #include #include @@ -23,55 +25,7 @@ static_assert(graphql::internal::MajorVersion == 5, "regenerate with schemagen: major version mismatch"); static_assert(graphql::internal::MinorVersion == 0, "regenerate with schemagen: minor version mismatch"); -namespace graphql { -namespace learn { - -enum class [[nodiscard("unnecessary conversion")]] Episode -{ - NEW_HOPE, - EMPIRE, - JEDI -}; - -[[nodiscard("unnecessary call")]] constexpr auto getEpisodeNames() noexcept -{ - using namespace std::literals; - - return std::array { - R"gql(NEW_HOPE)gql"sv, - R"gql(EMPIRE)gql"sv, - R"gql(JEDI)gql"sv - }; -} - -[[nodiscard("unnecessary call")]] constexpr auto getEpisodeValues() noexcept -{ - using namespace std::literals; - - return std::array, 3> { - std::make_pair(R"gql(JEDI)gql"sv, Episode::JEDI), - std::make_pair(R"gql(EMPIRE)gql"sv, Episode::EMPIRE), - std::make_pair(R"gql(NEW_HOPE)gql"sv, Episode::NEW_HOPE) - }; -} - -struct [[nodiscard("unnecessary construction")]] ReviewInput -{ - explicit ReviewInput() noexcept; - explicit ReviewInput( - int starsArg, - std::optional commentaryArg) noexcept; - ReviewInput(const ReviewInput& other); - ReviewInput(ReviewInput&& other) noexcept; - ~ReviewInput(); - - ReviewInput& operator=(const ReviewInput& other); - ReviewInput& operator=(ReviewInput&& other) noexcept; - - int stars; - std::optional commentary; -}; - +namespace graphql::learn { namespace object { class Character; @@ -118,7 +72,6 @@ void AddSubscriptionDetails(const std::shared_ptr& typeSubsc std::shared_ptr GetSchema(); -} // namespace learn -} // namespace graphql +} // namespace graphql::learn #endif // STARWARSSCHEMA_H diff --git a/samples/learn/schema/StarWarsSchema.ixx b/samples/learn/schema/StarWarsSchema.ixx index 1a339c7c..838f2815 100644 --- a/samples/learn/schema/StarWarsSchema.ixx +++ b/samples/learn/schema/StarWarsSchema.ixx @@ -9,6 +9,8 @@ module; export module GraphQL.StarWars.StarWarsSchema; +export import GraphQL.StarWars.StarWarsSharedTypes; + export import GraphQL.StarWars.CharacterObject; export import GraphQL.StarWars.HumanObject; export import GraphQL.StarWars.DroidObject; @@ -19,12 +21,6 @@ export import GraphQL.StarWars.SubscriptionObject; export namespace graphql::learn { -using learn::Episode; -using learn::getEpisodeNames; -using learn::getEpisodeValues; - -using learn::ReviewInput; - using learn::Operations; using learn::AddCharacterDetails; diff --git a/samples/learn/schema/StarWarsSharedTypes.cpp b/samples/learn/schema/StarWarsSharedTypes.cpp new file mode 100644 index 00000000..3bfcae45 --- /dev/null +++ b/samples/learn/schema/StarWarsSharedTypes.cpp @@ -0,0 +1,146 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// WARNING! Do not edit this file manually, your changes will be overwritten. + +#include "graphqlservice/GraphQLService.h" + +#include "StarWarsSharedTypes.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std::literals; + +namespace graphql { +namespace service { + +static const auto s_namesEpisode = learn::getEpisodeNames(); +static const auto s_valuesEpisode = learn::getEpisodeValues(); + +template <> +learn::Episode Argument::convert(const response::Value& value) +{ + if (!value.maybe_enum()) + { + throw service::schema_exception { { R"ex(not a valid Episode value)ex" } }; + } + + const auto result = internal::sorted_map_lookup( + s_valuesEpisode, + std::string_view { value.get() }); + + if (!result) + { + throw service::schema_exception { { R"ex(not a valid Episode value)ex" } }; + } + + return *result; +} + +template <> +service::AwaitableResolver Result::convert(service::AwaitableScalar result, ResolverParams&& params) +{ + return ModifiedResult::resolve(std::move(result), std::move(params), + [](learn::Episode value, const ResolverParams&) + { + response::Value resolvedResult(response::Type::EnumValue); + + resolvedResult.set(std::string { s_namesEpisode[static_cast(value)] }); + + return resolvedResult; + }); +} + +template <> +void Result::validateScalar(const response::Value& value) +{ + if (!value.maybe_enum()) + { + throw service::schema_exception { { R"ex(not a valid Episode value)ex" } }; + } + + const auto [itr, itrEnd] = internal::sorted_map_equal_range( + s_valuesEpisode.begin(), + s_valuesEpisode.end(), + std::string_view { value.get() }); + + if (itr == itrEnd) + { + throw service::schema_exception { { R"ex(not a valid Episode value)ex" } }; + } +} + +template <> +learn::ReviewInput Argument::convert(const response::Value& value) +{ + auto valueStars = service::ModifiedArgument::require("stars", value); + auto valueCommentary = service::ModifiedArgument::require("commentary", value); + + return learn::ReviewInput { + valueStars, + std::move(valueCommentary) + }; +} + +} // namespace service + +namespace learn { + +ReviewInput::ReviewInput() noexcept + : stars {} + , commentary {} +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +ReviewInput::ReviewInput( + int starsArg, + std::optional commentaryArg) noexcept + : stars { std::move(starsArg) } + , commentary { std::move(commentaryArg) } +{ +} + +ReviewInput::ReviewInput(const ReviewInput& other) + : stars { service::ModifiedArgument::duplicate(other.stars) } + , commentary { service::ModifiedArgument::duplicate(other.commentary) } +{ +} + +ReviewInput::ReviewInput(ReviewInput&& other) noexcept + : stars { std::move(other.stars) } + , commentary { std::move(other.commentary) } +{ +} + +ReviewInput::~ReviewInput() +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +ReviewInput& ReviewInput::operator=(const ReviewInput& other) +{ + ReviewInput value { other }; + + std::swap(*this, value); + + return *this; +} + +ReviewInput& ReviewInput::operator=(ReviewInput&& other) noexcept +{ + stars = std::move(other.stars); + commentary = std::move(other.commentary); + + return *this; +} + +} // namespace learn +} // namespace graphql diff --git a/samples/learn/schema/StarWarsSharedTypes.h b/samples/learn/schema/StarWarsSharedTypes.h new file mode 100644 index 00000000..b9dee9da --- /dev/null +++ b/samples/learn/schema/StarWarsSharedTypes.h @@ -0,0 +1,78 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// WARNING! Do not edit this file manually, your changes will be overwritten. + +#pragma once + +#ifndef STARWARSSHAREDTYPES_H +#define STARWARSSHAREDTYPES_H + +#include "graphqlservice/GraphQLResponse.h" + +#include "graphqlservice/internal/Version.h" + +#include +#include +#include +#include +#include +#include + +// Check if the library version is compatible with schemagen 5.0.0 +static_assert(graphql::internal::MajorVersion == 5, "regenerate with schemagen: major version mismatch"); +static_assert(graphql::internal::MinorVersion == 0, "regenerate with schemagen: minor version mismatch"); + +namespace graphql { +namespace learn { + +enum class [[nodiscard("unnecessary conversion")]] Episode +{ + NEW_HOPE, + EMPIRE, + JEDI +}; + +[[nodiscard("unnecessary call")]] constexpr auto getEpisodeNames() noexcept +{ + using namespace std::literals; + + return std::array { + R"gql(NEW_HOPE)gql"sv, + R"gql(EMPIRE)gql"sv, + R"gql(JEDI)gql"sv + }; +} + +[[nodiscard("unnecessary call")]] constexpr auto getEpisodeValues() noexcept +{ + using namespace std::literals; + + return std::array, 3> { + std::make_pair(R"gql(JEDI)gql"sv, Episode::JEDI), + std::make_pair(R"gql(EMPIRE)gql"sv, Episode::EMPIRE), + std::make_pair(R"gql(NEW_HOPE)gql"sv, Episode::NEW_HOPE) + }; +} + +struct [[nodiscard("unnecessary construction")]] ReviewInput +{ + explicit ReviewInput() noexcept; + explicit ReviewInput( + int starsArg, + std::optional commentaryArg) noexcept; + ReviewInput(const ReviewInput& other); + ReviewInput(ReviewInput&& other) noexcept; + ~ReviewInput(); + + ReviewInput& operator=(const ReviewInput& other); + ReviewInput& operator=(ReviewInput&& other) noexcept; + + int stars; + std::optional commentary; +}; + +} // namespace learn +} // namespace graphql + +#endif // STARWARSSHAREDTYPES_H diff --git a/samples/learn/schema/StarWarsSharedTypes.ixx b/samples/learn/schema/StarWarsSharedTypes.ixx new file mode 100644 index 00000000..5e6a2fa2 --- /dev/null +++ b/samples/learn/schema/StarWarsSharedTypes.ixx @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// WARNING! Do not edit this file manually, your changes will be overwritten. + +module; + +#include "StarWarsSharedTypes.h" + +export module GraphQL.StarWars.StarWarsSharedTypes; + +export namespace graphql::learn { + +using learn::Episode; +using learn::getEpisodeNames; +using learn::getEpisodeValues; + +using learn::ReviewInput; + +} // namespace graphql::learn diff --git a/samples/learn/schema/learn_schema_files b/samples/learn/schema/learn_schema_files index 3b3fc41b..4f26ca5c 100644 --- a/samples/learn/schema/learn_schema_files +++ b/samples/learn/schema/learn_schema_files @@ -1,3 +1,4 @@ +StarWarsSharedTypes.cpp StarWarsSchema.cpp CharacterObject.cpp HumanObject.cpp diff --git a/samples/proxy/query/ProxyClient.h b/samples/proxy/query/ProxyClient.h index f541794f..58669b8f 100644 --- a/samples/proxy/query/ProxyClient.h +++ b/samples/proxy/query/ProxyClient.h @@ -14,7 +14,7 @@ #include "graphqlservice/internal/Version.h" -#include "ProxySchema.h" +#include "ProxySharedTypes.h" #include #include diff --git a/samples/proxy/schema/ProxySchema.cpp b/samples/proxy/schema/ProxySchema.cpp index 5f2c26b4..5bb1337b 100644 --- a/samples/proxy/schema/ProxySchema.cpp +++ b/samples/proxy/schema/ProxySchema.cpp @@ -20,145 +20,7 @@ using namespace std::literals; -namespace graphql { -namespace service { - -static const auto s_namesOperationType = proxy::getOperationTypeNames(); -static const auto s_valuesOperationType = proxy::getOperationTypeValues(); - -template <> -proxy::OperationType Argument::convert(const response::Value& value) -{ - if (!value.maybe_enum()) - { - throw service::schema_exception { { R"ex(not a valid OperationType value)ex" } }; - } - - const auto result = internal::sorted_map_lookup( - s_valuesOperationType, - std::string_view { value.get() }); - - if (!result) - { - throw service::schema_exception { { R"ex(not a valid OperationType value)ex" } }; - } - - return *result; -} - -template <> -service::AwaitableResolver Result::convert(service::AwaitableScalar result, ResolverParams&& params) -{ - return ModifiedResult::resolve(std::move(result), std::move(params), - [](proxy::OperationType value, const ResolverParams&) - { - response::Value resolvedResult(response::Type::EnumValue); - - resolvedResult.set(std::string { s_namesOperationType[static_cast(value)] }); - - return resolvedResult; - }); -} - -template <> -void Result::validateScalar(const response::Value& value) -{ - if (!value.maybe_enum()) - { - throw service::schema_exception { { R"ex(not a valid OperationType value)ex" } }; - } - - const auto [itr, itrEnd] = internal::sorted_map_equal_range( - s_valuesOperationType.begin(), - s_valuesOperationType.end(), - std::string_view { value.get() }); - - if (itr == itrEnd) - { - throw service::schema_exception { { R"ex(not a valid OperationType value)ex" } }; - } -} - -template <> -proxy::QueryInput Argument::convert(const response::Value& value) -{ - auto valueType = service::ModifiedArgument::require("type", value); - auto valueQuery = service::ModifiedArgument::require("query", value); - auto valueOperationName = service::ModifiedArgument::require("operationName", value); - auto valueVariables = service::ModifiedArgument::require("variables", value); - - return proxy::QueryInput { - std::move(valueType), - std::move(valueQuery), - std::move(valueOperationName), - std::move(valueVariables) - }; -} - -} // namespace service - -namespace proxy { - -QueryInput::QueryInput() noexcept - : type {} - , query {} - , operationName {} - , variables {} -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -QueryInput::QueryInput( - OperationType typeArg, - std::string queryArg, - std::optional operationNameArg, - std::optional variablesArg) noexcept - : type { std::move(typeArg) } - , query { std::move(queryArg) } - , operationName { std::move(operationNameArg) } - , variables { std::move(variablesArg) } -{ -} - -QueryInput::QueryInput(const QueryInput& other) - : type { service::ModifiedArgument::duplicate(other.type) } - , query { service::ModifiedArgument::duplicate(other.query) } - , operationName { service::ModifiedArgument::duplicate(other.operationName) } - , variables { service::ModifiedArgument::duplicate(other.variables) } -{ -} - -QueryInput::QueryInput(QueryInput&& other) noexcept - : type { std::move(other.type) } - , query { std::move(other.query) } - , operationName { std::move(other.operationName) } - , variables { std::move(other.variables) } -{ -} - -QueryInput::~QueryInput() -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -QueryInput& QueryInput::operator=(const QueryInput& other) -{ - QueryInput value { other }; - - std::swap(*this, value); - - return *this; -} - -QueryInput& QueryInput::operator=(QueryInput&& other) noexcept -{ - type = std::move(other.type); - query = std::move(other.query); - operationName = std::move(other.operationName); - variables = std::move(other.variables); - - return *this; -} +namespace graphql::proxy { Operations::Operations(std::shared_ptr query) : service::Request({ @@ -179,10 +41,11 @@ void AddTypesToSchema(const std::shared_ptr& schema) auto typeQueryResults = schema::ObjectType::Make(R"gql(QueryResults)gql"sv, R"md()md"sv); schema->AddType(R"gql(QueryResults)gql"sv, typeQueryResults); + static const auto s_namesOperationType = getOperationTypeNames(); typeOperationType->AddEnumValues({ - { service::s_namesOperationType[static_cast(proxy::OperationType::QUERY)], R"md()md"sv, std::nullopt }, - { service::s_namesOperationType[static_cast(proxy::OperationType::MUTATION)], R"md()md"sv, std::nullopt }, - { service::s_namesOperationType[static_cast(proxy::OperationType::SUBSCRIPTION)], R"md()md"sv, std::nullopt } + { s_namesOperationType[static_cast(proxy::OperationType::QUERY)], R"md()md"sv, std::nullopt }, + { s_namesOperationType[static_cast(proxy::OperationType::MUTATION)], R"md()md"sv, std::nullopt }, + { s_namesOperationType[static_cast(proxy::OperationType::SUBSCRIPTION)], R"md()md"sv, std::nullopt } }); typeQueryInput->AddInputValues({ @@ -214,5 +77,4 @@ std::shared_ptr GetSchema() return schema; } -} // namespace proxy -} // namespace graphql +} // namespace graphql::proxy diff --git a/samples/proxy/schema/ProxySchema.h b/samples/proxy/schema/ProxySchema.h index 849cfb60..bbaa0e6c 100644 --- a/samples/proxy/schema/ProxySchema.h +++ b/samples/proxy/schema/ProxySchema.h @@ -14,6 +14,8 @@ #include "graphqlservice/internal/Version.h" #include "graphqlservice/internal/Schema.h" +#include "ProxySharedTypes.h" + #include #include #include @@ -23,59 +25,7 @@ static_assert(graphql::internal::MajorVersion == 5, "regenerate with schemagen: major version mismatch"); static_assert(graphql::internal::MinorVersion == 0, "regenerate with schemagen: minor version mismatch"); -namespace graphql { -namespace proxy { - -enum class [[nodiscard("unnecessary conversion")]] OperationType -{ - QUERY, - MUTATION, - SUBSCRIPTION -}; - -[[nodiscard("unnecessary call")]] constexpr auto getOperationTypeNames() noexcept -{ - using namespace std::literals; - - return std::array { - R"gql(QUERY)gql"sv, - R"gql(MUTATION)gql"sv, - R"gql(SUBSCRIPTION)gql"sv - }; -} - -[[nodiscard("unnecessary call")]] constexpr auto getOperationTypeValues() noexcept -{ - using namespace std::literals; - - return std::array, 3> { - std::make_pair(R"gql(QUERY)gql"sv, OperationType::QUERY), - std::make_pair(R"gql(MUTATION)gql"sv, OperationType::MUTATION), - std::make_pair(R"gql(SUBSCRIPTION)gql"sv, OperationType::SUBSCRIPTION) - }; -} - -struct [[nodiscard("unnecessary construction")]] QueryInput -{ - explicit QueryInput() noexcept; - explicit QueryInput( - OperationType typeArg, - std::string queryArg, - std::optional operationNameArg, - std::optional variablesArg) noexcept; - QueryInput(const QueryInput& other); - QueryInput(QueryInput&& other) noexcept; - ~QueryInput(); - - QueryInput& operator=(const QueryInput& other); - QueryInput& operator=(QueryInput&& other) noexcept; - - OperationType type; - std::string query; - std::optional operationName; - std::optional variables; -}; - +namespace graphql::proxy { namespace object { class Query; @@ -106,7 +56,6 @@ void AddQueryResultsDetails(const std::shared_ptr& typeQuery std::shared_ptr GetSchema(); -} // namespace proxy -} // namespace graphql +} // namespace graphql::proxy #endif // PROXYSCHEMA_H diff --git a/samples/proxy/schema/ProxySchema.ixx b/samples/proxy/schema/ProxySchema.ixx index 0b646c10..6e5893e3 100644 --- a/samples/proxy/schema/ProxySchema.ixx +++ b/samples/proxy/schema/ProxySchema.ixx @@ -9,17 +9,13 @@ module; export module GraphQL.Proxy.ProxySchema; +export import GraphQL.Proxy.ProxySharedTypes; + export import GraphQL.Proxy.QueryObject; export import GraphQL.Proxy.QueryResultsObject; export namespace graphql::proxy { -using proxy::OperationType; -using proxy::getOperationTypeNames; -using proxy::getOperationTypeValues; - -using proxy::QueryInput; - using proxy::Operations; using proxy::AddQueryDetails; diff --git a/samples/proxy/schema/ProxySharedTypes.cpp b/samples/proxy/schema/ProxySharedTypes.cpp new file mode 100644 index 00000000..66aafa00 --- /dev/null +++ b/samples/proxy/schema/ProxySharedTypes.cpp @@ -0,0 +1,162 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// WARNING! Do not edit this file manually, your changes will be overwritten. + +#include "graphqlservice/GraphQLService.h" + +#include "ProxySharedTypes.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std::literals; + +namespace graphql { +namespace service { + +static const auto s_namesOperationType = proxy::getOperationTypeNames(); +static const auto s_valuesOperationType = proxy::getOperationTypeValues(); + +template <> +proxy::OperationType Argument::convert(const response::Value& value) +{ + if (!value.maybe_enum()) + { + throw service::schema_exception { { R"ex(not a valid OperationType value)ex" } }; + } + + const auto result = internal::sorted_map_lookup( + s_valuesOperationType, + std::string_view { value.get() }); + + if (!result) + { + throw service::schema_exception { { R"ex(not a valid OperationType value)ex" } }; + } + + return *result; +} + +template <> +service::AwaitableResolver Result::convert(service::AwaitableScalar result, ResolverParams&& params) +{ + return ModifiedResult::resolve(std::move(result), std::move(params), + [](proxy::OperationType value, const ResolverParams&) + { + response::Value resolvedResult(response::Type::EnumValue); + + resolvedResult.set(std::string { s_namesOperationType[static_cast(value)] }); + + return resolvedResult; + }); +} + +template <> +void Result::validateScalar(const response::Value& value) +{ + if (!value.maybe_enum()) + { + throw service::schema_exception { { R"ex(not a valid OperationType value)ex" } }; + } + + const auto [itr, itrEnd] = internal::sorted_map_equal_range( + s_valuesOperationType.begin(), + s_valuesOperationType.end(), + std::string_view { value.get() }); + + if (itr == itrEnd) + { + throw service::schema_exception { { R"ex(not a valid OperationType value)ex" } }; + } +} + +template <> +proxy::QueryInput Argument::convert(const response::Value& value) +{ + auto valueType = service::ModifiedArgument::require("type", value); + auto valueQuery = service::ModifiedArgument::require("query", value); + auto valueOperationName = service::ModifiedArgument::require("operationName", value); + auto valueVariables = service::ModifiedArgument::require("variables", value); + + return proxy::QueryInput { + std::move(valueType), + std::move(valueQuery), + std::move(valueOperationName), + std::move(valueVariables) + }; +} + +} // namespace service + +namespace proxy { + +QueryInput::QueryInput() noexcept + : type {} + , query {} + , operationName {} + , variables {} +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +QueryInput::QueryInput( + OperationType typeArg, + std::string queryArg, + std::optional operationNameArg, + std::optional variablesArg) noexcept + : type { std::move(typeArg) } + , query { std::move(queryArg) } + , operationName { std::move(operationNameArg) } + , variables { std::move(variablesArg) } +{ +} + +QueryInput::QueryInput(const QueryInput& other) + : type { service::ModifiedArgument::duplicate(other.type) } + , query { service::ModifiedArgument::duplicate(other.query) } + , operationName { service::ModifiedArgument::duplicate(other.operationName) } + , variables { service::ModifiedArgument::duplicate(other.variables) } +{ +} + +QueryInput::QueryInput(QueryInput&& other) noexcept + : type { std::move(other.type) } + , query { std::move(other.query) } + , operationName { std::move(other.operationName) } + , variables { std::move(other.variables) } +{ +} + +QueryInput::~QueryInput() +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +QueryInput& QueryInput::operator=(const QueryInput& other) +{ + QueryInput value { other }; + + std::swap(*this, value); + + return *this; +} + +QueryInput& QueryInput::operator=(QueryInput&& other) noexcept +{ + type = std::move(other.type); + query = std::move(other.query); + operationName = std::move(other.operationName); + variables = std::move(other.variables); + + return *this; +} + +} // namespace proxy +} // namespace graphql diff --git a/samples/proxy/schema/ProxySharedTypes.h b/samples/proxy/schema/ProxySharedTypes.h new file mode 100644 index 00000000..56ec1fa1 --- /dev/null +++ b/samples/proxy/schema/ProxySharedTypes.h @@ -0,0 +1,82 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// WARNING! Do not edit this file manually, your changes will be overwritten. + +#pragma once + +#ifndef PROXYSHAREDTYPES_H +#define PROXYSHAREDTYPES_H + +#include "graphqlservice/GraphQLResponse.h" + +#include "graphqlservice/internal/Version.h" + +#include +#include +#include +#include +#include +#include + +// Check if the library version is compatible with schemagen 5.0.0 +static_assert(graphql::internal::MajorVersion == 5, "regenerate with schemagen: major version mismatch"); +static_assert(graphql::internal::MinorVersion == 0, "regenerate with schemagen: minor version mismatch"); + +namespace graphql { +namespace proxy { + +enum class [[nodiscard("unnecessary conversion")]] OperationType +{ + QUERY, + MUTATION, + SUBSCRIPTION +}; + +[[nodiscard("unnecessary call")]] constexpr auto getOperationTypeNames() noexcept +{ + using namespace std::literals; + + return std::array { + R"gql(QUERY)gql"sv, + R"gql(MUTATION)gql"sv, + R"gql(SUBSCRIPTION)gql"sv + }; +} + +[[nodiscard("unnecessary call")]] constexpr auto getOperationTypeValues() noexcept +{ + using namespace std::literals; + + return std::array, 3> { + std::make_pair(R"gql(QUERY)gql"sv, OperationType::QUERY), + std::make_pair(R"gql(MUTATION)gql"sv, OperationType::MUTATION), + std::make_pair(R"gql(SUBSCRIPTION)gql"sv, OperationType::SUBSCRIPTION) + }; +} + +struct [[nodiscard("unnecessary construction")]] QueryInput +{ + explicit QueryInput() noexcept; + explicit QueryInput( + OperationType typeArg, + std::string queryArg, + std::optional operationNameArg, + std::optional variablesArg) noexcept; + QueryInput(const QueryInput& other); + QueryInput(QueryInput&& other) noexcept; + ~QueryInput(); + + QueryInput& operator=(const QueryInput& other); + QueryInput& operator=(QueryInput&& other) noexcept; + + OperationType type; + std::string query; + std::optional operationName; + std::optional variables; +}; + +} // namespace proxy +} // namespace graphql + +#endif // PROXYSHAREDTYPES_H diff --git a/samples/proxy/schema/ProxySharedTypes.ixx b/samples/proxy/schema/ProxySharedTypes.ixx new file mode 100644 index 00000000..75dd847d --- /dev/null +++ b/samples/proxy/schema/ProxySharedTypes.ixx @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// WARNING! Do not edit this file manually, your changes will be overwritten. + +module; + +#include "ProxySharedTypes.h" + +export module GraphQL.Proxy.ProxySharedTypes; + +export namespace graphql::proxy { + +using proxy::OperationType; +using proxy::getOperationTypeNames; +using proxy::getOperationTypeValues; + +using proxy::QueryInput; + +} // namespace graphql::proxy diff --git a/samples/proxy/schema/proxy_schema_files b/samples/proxy/schema/proxy_schema_files index 3b54c3a5..abca35d2 100644 --- a/samples/proxy/schema/proxy_schema_files +++ b/samples/proxy/schema/proxy_schema_files @@ -1,3 +1,4 @@ +ProxySharedTypes.cpp ProxySchema.cpp QueryObject.cpp QueryResultsObject.cpp diff --git a/samples/today/nointrospection/TodaySchema.cpp b/samples/today/nointrospection/TodaySchema.cpp index cb72d659..98cf8f6d 100644 --- a/samples/today/nointrospection/TodaySchema.cpp +++ b/samples/today/nointrospection/TodaySchema.cpp @@ -22,711 +22,7 @@ using namespace std::literals; -namespace graphql { -namespace service { - -static const auto s_namesTaskState = today::getTaskStateNames(); -static const auto s_valuesTaskState = today::getTaskStateValues(); - -template <> -today::TaskState Argument::convert(const response::Value& value) -{ - if (!value.maybe_enum()) - { - throw service::schema_exception { { R"ex(not a valid TaskState value)ex" } }; - } - - const auto result = internal::sorted_map_lookup( - s_valuesTaskState, - std::string_view { value.get() }); - - if (!result) - { - throw service::schema_exception { { R"ex(not a valid TaskState value)ex" } }; - } - - return *result; -} - -template <> -service::AwaitableResolver Result::convert(service::AwaitableScalar result, ResolverParams&& params) -{ - return ModifiedResult::resolve(std::move(result), std::move(params), - [](today::TaskState value, const ResolverParams&) - { - response::Value resolvedResult(response::Type::EnumValue); - - resolvedResult.set(std::string { s_namesTaskState[static_cast(value)] }); - - return resolvedResult; - }); -} - -template <> -void Result::validateScalar(const response::Value& value) -{ - if (!value.maybe_enum()) - { - throw service::schema_exception { { R"ex(not a valid TaskState value)ex" } }; - } - - const auto [itr, itrEnd] = internal::sorted_map_equal_range( - s_valuesTaskState.begin(), - s_valuesTaskState.end(), - std::string_view { value.get() }); - - if (itr == itrEnd) - { - throw service::schema_exception { { R"ex(not a valid TaskState value)ex" } }; - } -} - -template <> -today::CompleteTaskInput Argument::convert(const response::Value& value) -{ - const auto defaultValue = []() - { - response::Value values(response::Type::Map); - response::Value entry; - - entry = response::Value(true); - values.emplace_back("isComplete", std::move(entry)); - - return values; - }(); - - auto valueId = service::ModifiedArgument::require("id", value); - auto valueTestTaskState = service::ModifiedArgument::require("testTaskState", value); - auto pairIsComplete = service::ModifiedArgument::find("isComplete", value); - auto valueIsComplete = (pairIsComplete.second - ? std::move(pairIsComplete.first) - : service::ModifiedArgument::require("isComplete", defaultValue)); - auto valueClientMutationId = service::ModifiedArgument::require("clientMutationId", value); - - return today::CompleteTaskInput { - std::move(valueId), - valueTestTaskState, - std::move(valueIsComplete), - std::move(valueClientMutationId) - }; -} - -template <> -today::ThirdNestedInput Argument::convert(const response::Value& value) -{ - auto valueId = service::ModifiedArgument::require("id", value); - auto valueSecond = service::ModifiedArgument::require("second", value); - - return today::ThirdNestedInput { - std::move(valueId), - std::move(valueSecond) - }; -} - -template <> -today::FourthNestedInput Argument::convert(const response::Value& value) -{ - auto valueId = service::ModifiedArgument::require("id", value); - - return today::FourthNestedInput { - std::move(valueId) - }; -} - -template <> -today::IncludeNullableSelfInput Argument::convert(const response::Value& value) -{ - auto valueSelf = service::ModifiedArgument::require("self", value); - - return today::IncludeNullableSelfInput { - std::move(valueSelf) - }; -} - -template <> -today::IncludeNonNullableListSelfInput Argument::convert(const response::Value& value) -{ - auto valueSelves = service::ModifiedArgument::require("selves", value); - - return today::IncludeNonNullableListSelfInput { - std::move(valueSelves) - }; -} - -template <> -today::StringOperationFilterInput Argument::convert(const response::Value& value) -{ - auto valueAnd_ = service::ModifiedArgument::require("and", value); - auto valueOr_ = service::ModifiedArgument::require("or", value); - auto valueEqual = service::ModifiedArgument::require("equal", value); - auto valueNotEqual = service::ModifiedArgument::require("notEqual", value); - auto valueContains = service::ModifiedArgument::require("contains", value); - auto valueNotContains = service::ModifiedArgument::require("notContains", value); - auto valueIn = service::ModifiedArgument::require("in", value); - auto valueNotIn = service::ModifiedArgument::require("notIn", value); - auto valueStartsWith = service::ModifiedArgument::require("startsWith", value); - auto valueNotStartsWith = service::ModifiedArgument::require("notStartsWith", value); - auto valueEndsWith = service::ModifiedArgument::require("endsWith", value); - auto valueNotEndsWith = service::ModifiedArgument::require("notEndsWith", value); - - return today::StringOperationFilterInput { - std::move(valueAnd_), - std::move(valueOr_), - std::move(valueEqual), - std::move(valueNotEqual), - std::move(valueContains), - std::move(valueNotContains), - std::move(valueIn), - std::move(valueNotIn), - std::move(valueStartsWith), - std::move(valueNotStartsWith), - std::move(valueEndsWith), - std::move(valueNotEndsWith) - }; -} - -template <> -today::SecondNestedInput Argument::convert(const response::Value& value) -{ - auto valueId = service::ModifiedArgument::require("id", value); - auto valueThird = service::ModifiedArgument::require("third", value); - - return today::SecondNestedInput { - std::move(valueId), - std::move(valueThird) - }; -} - -template <> -today::ForwardDeclaredInput Argument::convert(const response::Value& value) -{ - auto valueNullableSelf = service::ModifiedArgument::require("nullableSelf", value); - auto valueListSelves = service::ModifiedArgument::require("listSelves", value); - - return today::ForwardDeclaredInput { - std::move(valueNullableSelf), - std::move(valueListSelves) - }; -} - -template <> -today::FirstNestedInput Argument::convert(const response::Value& value) -{ - auto valueId = service::ModifiedArgument::require("id", value); - auto valueSecond = service::ModifiedArgument::require("second", value); - auto valueThird = service::ModifiedArgument::require("third", value); - - return today::FirstNestedInput { - std::move(valueId), - std::move(valueSecond), - std::move(valueThird) - }; -} - -} // namespace service - -namespace today { - -CompleteTaskInput::CompleteTaskInput() noexcept - : id {} - , testTaskState {} - , isComplete {} - , clientMutationId {} -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -CompleteTaskInput::CompleteTaskInput( - response::IdType idArg, - std::optional testTaskStateArg, - std::optional isCompleteArg, - std::optional clientMutationIdArg) noexcept - : id { std::move(idArg) } - , testTaskState { std::move(testTaskStateArg) } - , isComplete { std::move(isCompleteArg) } - , clientMutationId { std::move(clientMutationIdArg) } -{ -} - -CompleteTaskInput::CompleteTaskInput(const CompleteTaskInput& other) - : id { service::ModifiedArgument::duplicate(other.id) } - , testTaskState { service::ModifiedArgument::duplicate(other.testTaskState) } - , isComplete { service::ModifiedArgument::duplicate(other.isComplete) } - , clientMutationId { service::ModifiedArgument::duplicate(other.clientMutationId) } -{ -} - -CompleteTaskInput::CompleteTaskInput(CompleteTaskInput&& other) noexcept - : id { std::move(other.id) } - , testTaskState { std::move(other.testTaskState) } - , isComplete { std::move(other.isComplete) } - , clientMutationId { std::move(other.clientMutationId) } -{ -} - -CompleteTaskInput::~CompleteTaskInput() -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -CompleteTaskInput& CompleteTaskInput::operator=(const CompleteTaskInput& other) -{ - CompleteTaskInput value { other }; - - std::swap(*this, value); - - return *this; -} - -CompleteTaskInput& CompleteTaskInput::operator=(CompleteTaskInput&& other) noexcept -{ - id = std::move(other.id); - testTaskState = std::move(other.testTaskState); - isComplete = std::move(other.isComplete); - clientMutationId = std::move(other.clientMutationId); - - return *this; -} - -ThirdNestedInput::ThirdNestedInput() noexcept - : id {} - , second {} -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -ThirdNestedInput::ThirdNestedInput( - response::IdType idArg, - std::unique_ptr secondArg) noexcept - : id { std::move(idArg) } - , second { std::move(secondArg) } -{ -} - -ThirdNestedInput::ThirdNestedInput(const ThirdNestedInput& other) - : id { service::ModifiedArgument::duplicate(other.id) } - , second { service::ModifiedArgument::duplicate(other.second) } -{ -} - -ThirdNestedInput::ThirdNestedInput(ThirdNestedInput&& other) noexcept - : id { std::move(other.id) } - , second { std::move(other.second) } -{ -} - -ThirdNestedInput::~ThirdNestedInput() -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -ThirdNestedInput& ThirdNestedInput::operator=(const ThirdNestedInput& other) -{ - ThirdNestedInput value { other }; - - std::swap(*this, value); - - return *this; -} - -ThirdNestedInput& ThirdNestedInput::operator=(ThirdNestedInput&& other) noexcept -{ - id = std::move(other.id); - second = std::move(other.second); - - return *this; -} - -FourthNestedInput::FourthNestedInput() noexcept - : id {} -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -FourthNestedInput::FourthNestedInput( - response::IdType idArg) noexcept - : id { std::move(idArg) } -{ -} - -FourthNestedInput::FourthNestedInput(const FourthNestedInput& other) - : id { service::ModifiedArgument::duplicate(other.id) } -{ -} - -FourthNestedInput::FourthNestedInput(FourthNestedInput&& other) noexcept - : id { std::move(other.id) } -{ -} - -FourthNestedInput::~FourthNestedInput() -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -FourthNestedInput& FourthNestedInput::operator=(const FourthNestedInput& other) -{ - FourthNestedInput value { other }; - - std::swap(*this, value); - - return *this; -} - -FourthNestedInput& FourthNestedInput::operator=(FourthNestedInput&& other) noexcept -{ - id = std::move(other.id); - - return *this; -} - -IncludeNullableSelfInput::IncludeNullableSelfInput() noexcept - : self {} -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -IncludeNullableSelfInput::IncludeNullableSelfInput( - std::unique_ptr selfArg) noexcept - : self { std::move(selfArg) } -{ -} - -IncludeNullableSelfInput::IncludeNullableSelfInput(const IncludeNullableSelfInput& other) - : self { service::ModifiedArgument::duplicate(other.self) } -{ -} - -IncludeNullableSelfInput::IncludeNullableSelfInput(IncludeNullableSelfInput&& other) noexcept - : self { std::move(other.self) } -{ -} - -IncludeNullableSelfInput::~IncludeNullableSelfInput() -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -IncludeNullableSelfInput& IncludeNullableSelfInput::operator=(const IncludeNullableSelfInput& other) -{ - IncludeNullableSelfInput value { other }; - - std::swap(*this, value); - - return *this; -} - -IncludeNullableSelfInput& IncludeNullableSelfInput::operator=(IncludeNullableSelfInput&& other) noexcept -{ - self = std::move(other.self); - - return *this; -} - -IncludeNonNullableListSelfInput::IncludeNonNullableListSelfInput() noexcept - : selves {} -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -IncludeNonNullableListSelfInput::IncludeNonNullableListSelfInput( - std::vector selvesArg) noexcept - : selves { std::move(selvesArg) } -{ -} - -IncludeNonNullableListSelfInput::IncludeNonNullableListSelfInput(const IncludeNonNullableListSelfInput& other) - : selves { service::ModifiedArgument::duplicate(other.selves) } -{ -} - -IncludeNonNullableListSelfInput::IncludeNonNullableListSelfInput(IncludeNonNullableListSelfInput&& other) noexcept - : selves { std::move(other.selves) } -{ -} - -IncludeNonNullableListSelfInput::~IncludeNonNullableListSelfInput() -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -IncludeNonNullableListSelfInput& IncludeNonNullableListSelfInput::operator=(const IncludeNonNullableListSelfInput& other) -{ - IncludeNonNullableListSelfInput value { other }; - - std::swap(*this, value); - - return *this; -} - -IncludeNonNullableListSelfInput& IncludeNonNullableListSelfInput::operator=(IncludeNonNullableListSelfInput&& other) noexcept -{ - selves = std::move(other.selves); - - return *this; -} - -StringOperationFilterInput::StringOperationFilterInput() noexcept - : and_ {} - , or_ {} - , equal {} - , notEqual {} - , contains {} - , notContains {} - , in {} - , notIn {} - , startsWith {} - , notStartsWith {} - , endsWith {} - , notEndsWith {} -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -StringOperationFilterInput::StringOperationFilterInput( - std::optional> and_Arg, - std::optional> or_Arg, - std::optional equalArg, - std::optional notEqualArg, - std::optional containsArg, - std::optional notContainsArg, - std::optional> inArg, - std::optional> notInArg, - std::optional startsWithArg, - std::optional notStartsWithArg, - std::optional endsWithArg, - std::optional notEndsWithArg) noexcept - : and_ { std::move(and_Arg) } - , or_ { std::move(or_Arg) } - , equal { std::move(equalArg) } - , notEqual { std::move(notEqualArg) } - , contains { std::move(containsArg) } - , notContains { std::move(notContainsArg) } - , in { std::move(inArg) } - , notIn { std::move(notInArg) } - , startsWith { std::move(startsWithArg) } - , notStartsWith { std::move(notStartsWithArg) } - , endsWith { std::move(endsWithArg) } - , notEndsWith { std::move(notEndsWithArg) } -{ -} - -StringOperationFilterInput::StringOperationFilterInput(const StringOperationFilterInput& other) - : and_ { service::ModifiedArgument::duplicate(other.and_) } - , or_ { service::ModifiedArgument::duplicate(other.or_) } - , equal { service::ModifiedArgument::duplicate(other.equal) } - , notEqual { service::ModifiedArgument::duplicate(other.notEqual) } - , contains { service::ModifiedArgument::duplicate(other.contains) } - , notContains { service::ModifiedArgument::duplicate(other.notContains) } - , in { service::ModifiedArgument::duplicate(other.in) } - , notIn { service::ModifiedArgument::duplicate(other.notIn) } - , startsWith { service::ModifiedArgument::duplicate(other.startsWith) } - , notStartsWith { service::ModifiedArgument::duplicate(other.notStartsWith) } - , endsWith { service::ModifiedArgument::duplicate(other.endsWith) } - , notEndsWith { service::ModifiedArgument::duplicate(other.notEndsWith) } -{ -} - -StringOperationFilterInput::StringOperationFilterInput(StringOperationFilterInput&& other) noexcept - : and_ { std::move(other.and_) } - , or_ { std::move(other.or_) } - , equal { std::move(other.equal) } - , notEqual { std::move(other.notEqual) } - , contains { std::move(other.contains) } - , notContains { std::move(other.notContains) } - , in { std::move(other.in) } - , notIn { std::move(other.notIn) } - , startsWith { std::move(other.startsWith) } - , notStartsWith { std::move(other.notStartsWith) } - , endsWith { std::move(other.endsWith) } - , notEndsWith { std::move(other.notEndsWith) } -{ -} - -StringOperationFilterInput::~StringOperationFilterInput() -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -StringOperationFilterInput& StringOperationFilterInput::operator=(const StringOperationFilterInput& other) -{ - StringOperationFilterInput value { other }; - - std::swap(*this, value); - - return *this; -} - -StringOperationFilterInput& StringOperationFilterInput::operator=(StringOperationFilterInput&& other) noexcept -{ - and_ = std::move(other.and_); - or_ = std::move(other.or_); - equal = std::move(other.equal); - notEqual = std::move(other.notEqual); - contains = std::move(other.contains); - notContains = std::move(other.notContains); - in = std::move(other.in); - notIn = std::move(other.notIn); - startsWith = std::move(other.startsWith); - notStartsWith = std::move(other.notStartsWith); - endsWith = std::move(other.endsWith); - notEndsWith = std::move(other.notEndsWith); - - return *this; -} - -SecondNestedInput::SecondNestedInput() noexcept - : id {} - , third {} -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -SecondNestedInput::SecondNestedInput( - response::IdType idArg, - ThirdNestedInput thirdArg) noexcept - : id { std::move(idArg) } - , third { std::move(thirdArg) } -{ -} - -SecondNestedInput::SecondNestedInput(const SecondNestedInput& other) - : id { service::ModifiedArgument::duplicate(other.id) } - , third { service::ModifiedArgument::duplicate(other.third) } -{ -} - -SecondNestedInput::SecondNestedInput(SecondNestedInput&& other) noexcept - : id { std::move(other.id) } - , third { std::move(other.third) } -{ -} - -SecondNestedInput::~SecondNestedInput() -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -SecondNestedInput& SecondNestedInput::operator=(const SecondNestedInput& other) -{ - SecondNestedInput value { other }; - - std::swap(*this, value); - - return *this; -} - -SecondNestedInput& SecondNestedInput::operator=(SecondNestedInput&& other) noexcept -{ - id = std::move(other.id); - third = std::move(other.third); - - return *this; -} - -ForwardDeclaredInput::ForwardDeclaredInput() noexcept - : nullableSelf {} - , listSelves {} -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -ForwardDeclaredInput::ForwardDeclaredInput( - std::unique_ptr nullableSelfArg, - IncludeNonNullableListSelfInput listSelvesArg) noexcept - : nullableSelf { std::move(nullableSelfArg) } - , listSelves { std::move(listSelvesArg) } -{ -} - -ForwardDeclaredInput::ForwardDeclaredInput(const ForwardDeclaredInput& other) - : nullableSelf { service::ModifiedArgument::duplicate(other.nullableSelf) } - , listSelves { service::ModifiedArgument::duplicate(other.listSelves) } -{ -} - -ForwardDeclaredInput::ForwardDeclaredInput(ForwardDeclaredInput&& other) noexcept - : nullableSelf { std::move(other.nullableSelf) } - , listSelves { std::move(other.listSelves) } -{ -} - -ForwardDeclaredInput::~ForwardDeclaredInput() -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -ForwardDeclaredInput& ForwardDeclaredInput::operator=(const ForwardDeclaredInput& other) -{ - ForwardDeclaredInput value { other }; - - std::swap(*this, value); - - return *this; -} - -ForwardDeclaredInput& ForwardDeclaredInput::operator=(ForwardDeclaredInput&& other) noexcept -{ - nullableSelf = std::move(other.nullableSelf); - listSelves = std::move(other.listSelves); - - return *this; -} - -FirstNestedInput::FirstNestedInput() noexcept - : id {} - , second {} - , third {} -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -FirstNestedInput::FirstNestedInput( - response::IdType idArg, - SecondNestedInput secondArg, - ThirdNestedInput thirdArg) noexcept - : id { std::move(idArg) } - , second { std::move(secondArg) } - , third { std::move(thirdArg) } -{ -} - -FirstNestedInput::FirstNestedInput(const FirstNestedInput& other) - : id { service::ModifiedArgument::duplicate(other.id) } - , second { service::ModifiedArgument::duplicate(other.second) } - , third { service::ModifiedArgument::duplicate(other.third) } -{ -} - -FirstNestedInput::FirstNestedInput(FirstNestedInput&& other) noexcept - : id { std::move(other.id) } - , second { std::move(other.second) } - , third { std::move(other.third) } -{ -} - -FirstNestedInput::~FirstNestedInput() -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -FirstNestedInput& FirstNestedInput::operator=(const FirstNestedInput& other) -{ - FirstNestedInput value { other }; - - std::swap(*this, value); - - return *this; -} - -FirstNestedInput& FirstNestedInput::operator=(FirstNestedInput&& other) noexcept -{ - id = std::move(other.id); - second = std::move(other.second); - third = std::move(other.third); - - return *this; -} +namespace graphql::today { Operations::Operations(std::shared_ptr query, std::shared_ptr mutation, std::shared_ptr subscription) : service::Request({ @@ -801,11 +97,12 @@ void AddTypesToSchema(const std::shared_ptr& schema) auto typeExpensive = schema::ObjectType::Make(R"gql(Expensive)gql"sv, R"md()md"sv); schema->AddType(R"gql(Expensive)gql"sv, typeExpensive); + static const auto s_namesTaskState = getTaskStateNames(); typeTaskState->AddEnumValues({ - { service::s_namesTaskState[static_cast(today::TaskState::Unassigned)], R"md()md"sv, std::make_optional(R"md(Need to deprecate an [enum value](https://spec.graphql.org/October2021/#sec-Schema-Introspection.Deprecation))md"sv) }, - { service::s_namesTaskState[static_cast(today::TaskState::New)], R"md()md"sv, std::nullopt }, - { service::s_namesTaskState[static_cast(today::TaskState::Started)], R"md()md"sv, std::nullopt }, - { service::s_namesTaskState[static_cast(today::TaskState::Complete)], R"md()md"sv, std::nullopt } + { s_namesTaskState[static_cast(today::TaskState::Unassigned)], R"md()md"sv, std::make_optional(R"md(Need to deprecate an [enum value](https://spec.graphql.org/October2021/#sec-Schema-Introspection.Deprecation))md"sv) }, + { s_namesTaskState[static_cast(today::TaskState::New)], R"md()md"sv, std::nullopt }, + { s_namesTaskState[static_cast(today::TaskState::Started)], R"md()md"sv, std::nullopt }, + { s_namesTaskState[static_cast(today::TaskState::Complete)], R"md()md"sv, std::nullopt } }); typeCompleteTaskInput->AddInputValues({ @@ -929,5 +226,4 @@ std::shared_ptr GetSchema() return schema; } -} // namespace today -} // namespace graphql +} // namespace graphql::today diff --git a/samples/today/nointrospection/TodaySchema.h b/samples/today/nointrospection/TodaySchema.h index 3798db11..80b99eee 100644 --- a/samples/today/nointrospection/TodaySchema.h +++ b/samples/today/nointrospection/TodaySchema.h @@ -14,6 +14,8 @@ #include "graphqlservice/internal/Version.h" #include "graphqlservice/internal/Schema.h" +#include "TodaySharedTypes.h" + #include #include #include @@ -23,216 +25,7 @@ static_assert(graphql::internal::MajorVersion == 5, "regenerate with schemagen: major version mismatch"); static_assert(graphql::internal::MinorVersion == 0, "regenerate with schemagen: minor version mismatch"); -namespace graphql { -namespace today { - -enum class [[nodiscard("unnecessary conversion")]] TaskState -{ - Unassigned, - New, - Started, - Complete -}; - -[[nodiscard("unnecessary call")]] constexpr auto getTaskStateNames() noexcept -{ - using namespace std::literals; - - return std::array { - R"gql(Unassigned)gql"sv, - R"gql(New)gql"sv, - R"gql(Started)gql"sv, - R"gql(Complete)gql"sv - }; -} - -[[nodiscard("unnecessary call")]] constexpr auto getTaskStateValues() noexcept -{ - using namespace std::literals; - - return std::array, 4> { - std::make_pair(R"gql(New)gql"sv, TaskState::New), - std::make_pair(R"gql(Started)gql"sv, TaskState::Started), - std::make_pair(R"gql(Complete)gql"sv, TaskState::Complete), - std::make_pair(R"gql(Unassigned)gql"sv, TaskState::Unassigned) - }; -} - -struct [[nodiscard("unnecessary construction")]] CompleteTaskInput -{ - explicit CompleteTaskInput() noexcept; - explicit CompleteTaskInput( - response::IdType idArg, - std::optional testTaskStateArg, - std::optional isCompleteArg, - std::optional clientMutationIdArg) noexcept; - CompleteTaskInput(const CompleteTaskInput& other); - CompleteTaskInput(CompleteTaskInput&& other) noexcept; - ~CompleteTaskInput(); - - CompleteTaskInput& operator=(const CompleteTaskInput& other); - CompleteTaskInput& operator=(CompleteTaskInput&& other) noexcept; - - response::IdType id; - std::optional testTaskState; - std::optional isComplete; - std::optional clientMutationId; -}; - -struct SecondNestedInput; - -struct [[nodiscard("unnecessary construction")]] ThirdNestedInput -{ - explicit ThirdNestedInput() noexcept; - explicit ThirdNestedInput( - response::IdType idArg, - std::unique_ptr secondArg) noexcept; - ThirdNestedInput(const ThirdNestedInput& other); - ThirdNestedInput(ThirdNestedInput&& other) noexcept; - ~ThirdNestedInput(); - - ThirdNestedInput& operator=(const ThirdNestedInput& other); - ThirdNestedInput& operator=(ThirdNestedInput&& other) noexcept; - - response::IdType id; - std::unique_ptr second; -}; - -struct [[nodiscard("unnecessary construction")]] FourthNestedInput -{ - explicit FourthNestedInput() noexcept; - explicit FourthNestedInput( - response::IdType idArg) noexcept; - FourthNestedInput(const FourthNestedInput& other); - FourthNestedInput(FourthNestedInput&& other) noexcept; - ~FourthNestedInput(); - - FourthNestedInput& operator=(const FourthNestedInput& other); - FourthNestedInput& operator=(FourthNestedInput&& other) noexcept; - - response::IdType id; -}; - -struct [[nodiscard("unnecessary construction")]] IncludeNullableSelfInput -{ - explicit IncludeNullableSelfInput() noexcept; - explicit IncludeNullableSelfInput( - std::unique_ptr selfArg) noexcept; - IncludeNullableSelfInput(const IncludeNullableSelfInput& other); - IncludeNullableSelfInput(IncludeNullableSelfInput&& other) noexcept; - ~IncludeNullableSelfInput(); - - IncludeNullableSelfInput& operator=(const IncludeNullableSelfInput& other); - IncludeNullableSelfInput& operator=(IncludeNullableSelfInput&& other) noexcept; - - std::unique_ptr self; -}; - -struct [[nodiscard("unnecessary construction")]] IncludeNonNullableListSelfInput -{ - explicit IncludeNonNullableListSelfInput() noexcept; - explicit IncludeNonNullableListSelfInput( - std::vector selvesArg) noexcept; - IncludeNonNullableListSelfInput(const IncludeNonNullableListSelfInput& other); - IncludeNonNullableListSelfInput(IncludeNonNullableListSelfInput&& other) noexcept; - ~IncludeNonNullableListSelfInput(); - - IncludeNonNullableListSelfInput& operator=(const IncludeNonNullableListSelfInput& other); - IncludeNonNullableListSelfInput& operator=(IncludeNonNullableListSelfInput&& other) noexcept; - - std::vector selves; -}; - -struct [[nodiscard("unnecessary construction")]] StringOperationFilterInput -{ - explicit StringOperationFilterInput() noexcept; - explicit StringOperationFilterInput( - std::optional> and_Arg, - std::optional> or_Arg, - std::optional equalArg, - std::optional notEqualArg, - std::optional containsArg, - std::optional notContainsArg, - std::optional> inArg, - std::optional> notInArg, - std::optional startsWithArg, - std::optional notStartsWithArg, - std::optional endsWithArg, - std::optional notEndsWithArg) noexcept; - StringOperationFilterInput(const StringOperationFilterInput& other); - StringOperationFilterInput(StringOperationFilterInput&& other) noexcept; - ~StringOperationFilterInput(); - - StringOperationFilterInput& operator=(const StringOperationFilterInput& other); - StringOperationFilterInput& operator=(StringOperationFilterInput&& other) noexcept; - - std::optional> and_; - std::optional> or_; - std::optional equal; - std::optional notEqual; - std::optional contains; - std::optional notContains; - std::optional> in; - std::optional> notIn; - std::optional startsWith; - std::optional notStartsWith; - std::optional endsWith; - std::optional notEndsWith; -}; - -struct [[nodiscard("unnecessary construction")]] SecondNestedInput -{ - explicit SecondNestedInput() noexcept; - explicit SecondNestedInput( - response::IdType idArg, - ThirdNestedInput thirdArg) noexcept; - SecondNestedInput(const SecondNestedInput& other); - SecondNestedInput(SecondNestedInput&& other) noexcept; - ~SecondNestedInput(); - - SecondNestedInput& operator=(const SecondNestedInput& other); - SecondNestedInput& operator=(SecondNestedInput&& other) noexcept; - - response::IdType id; - ThirdNestedInput third; -}; - -struct [[nodiscard("unnecessary construction")]] ForwardDeclaredInput -{ - explicit ForwardDeclaredInput() noexcept; - explicit ForwardDeclaredInput( - std::unique_ptr nullableSelfArg, - IncludeNonNullableListSelfInput listSelvesArg) noexcept; - ForwardDeclaredInput(const ForwardDeclaredInput& other); - ForwardDeclaredInput(ForwardDeclaredInput&& other) noexcept; - ~ForwardDeclaredInput(); - - ForwardDeclaredInput& operator=(const ForwardDeclaredInput& other); - ForwardDeclaredInput& operator=(ForwardDeclaredInput&& other) noexcept; - - std::unique_ptr nullableSelf; - IncludeNonNullableListSelfInput listSelves; -}; - -struct [[nodiscard("unnecessary construction")]] FirstNestedInput -{ - explicit FirstNestedInput() noexcept; - explicit FirstNestedInput( - response::IdType idArg, - SecondNestedInput secondArg, - ThirdNestedInput thirdArg) noexcept; - FirstNestedInput(const FirstNestedInput& other); - FirstNestedInput(FirstNestedInput&& other) noexcept; - ~FirstNestedInput(); - - FirstNestedInput& operator=(const FirstNestedInput& other); - FirstNestedInput& operator=(FirstNestedInput&& other) noexcept; - - response::IdType id; - SecondNestedInput second; - ThirdNestedInput third; -}; - +namespace graphql::today { namespace object { class Node; @@ -303,7 +96,6 @@ void AddExpensiveDetails(const std::shared_ptr& typeExpensiv std::shared_ptr GetSchema(); -} // namespace today -} // namespace graphql +} // namespace graphql::today #endif // TODAYSCHEMA_H diff --git a/samples/today/nointrospection/TodaySchema.ixx b/samples/today/nointrospection/TodaySchema.ixx index 7bfef47c..56aad8e6 100644 --- a/samples/today/nointrospection/TodaySchema.ixx +++ b/samples/today/nointrospection/TodaySchema.ixx @@ -9,6 +9,8 @@ module; export module GraphQL.Today.TodaySchema; +export import GraphQL.Today.TodaySharedTypes; + export import GraphQL.Today.NodeObject; export import GraphQL.Today.UnionTypeObject; export import GraphQL.Today.QueryObject; @@ -30,20 +32,6 @@ export import GraphQL.Today.ExpensiveObject; export namespace graphql::today { -using today::TaskState; -using today::getTaskStateNames; -using today::getTaskStateValues; - -using today::CompleteTaskInput; -using today::ThirdNestedInput; -using today::FourthNestedInput; -using today::IncludeNullableSelfInput; -using today::IncludeNonNullableListSelfInput; -using today::StringOperationFilterInput; -using today::SecondNestedInput; -using today::ForwardDeclaredInput; -using today::FirstNestedInput; - using today::Operations; using today::AddNodeDetails; diff --git a/samples/today/nointrospection/TodaySharedTypes.cpp b/samples/today/nointrospection/TodaySharedTypes.cpp new file mode 100644 index 00000000..d3a0c4a0 --- /dev/null +++ b/samples/today/nointrospection/TodaySharedTypes.cpp @@ -0,0 +1,736 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// WARNING! Do not edit this file manually, your changes will be overwritten. + +#include "graphqlservice/GraphQLService.h" + +#include "TodaySharedTypes.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std::literals; + +namespace graphql { +namespace service { + +static const auto s_namesTaskState = today::getTaskStateNames(); +static const auto s_valuesTaskState = today::getTaskStateValues(); + +template <> +today::TaskState Argument::convert(const response::Value& value) +{ + if (!value.maybe_enum()) + { + throw service::schema_exception { { R"ex(not a valid TaskState value)ex" } }; + } + + const auto result = internal::sorted_map_lookup( + s_valuesTaskState, + std::string_view { value.get() }); + + if (!result) + { + throw service::schema_exception { { R"ex(not a valid TaskState value)ex" } }; + } + + return *result; +} + +template <> +service::AwaitableResolver Result::convert(service::AwaitableScalar result, ResolverParams&& params) +{ + return ModifiedResult::resolve(std::move(result), std::move(params), + [](today::TaskState value, const ResolverParams&) + { + response::Value resolvedResult(response::Type::EnumValue); + + resolvedResult.set(std::string { s_namesTaskState[static_cast(value)] }); + + return resolvedResult; + }); +} + +template <> +void Result::validateScalar(const response::Value& value) +{ + if (!value.maybe_enum()) + { + throw service::schema_exception { { R"ex(not a valid TaskState value)ex" } }; + } + + const auto [itr, itrEnd] = internal::sorted_map_equal_range( + s_valuesTaskState.begin(), + s_valuesTaskState.end(), + std::string_view { value.get() }); + + if (itr == itrEnd) + { + throw service::schema_exception { { R"ex(not a valid TaskState value)ex" } }; + } +} + +template <> +today::CompleteTaskInput Argument::convert(const response::Value& value) +{ + const auto defaultValue = []() + { + response::Value values(response::Type::Map); + response::Value entry; + + entry = response::Value(true); + values.emplace_back("isComplete", std::move(entry)); + + return values; + }(); + + auto valueId = service::ModifiedArgument::require("id", value); + auto valueTestTaskState = service::ModifiedArgument::require("testTaskState", value); + auto pairIsComplete = service::ModifiedArgument::find("isComplete", value); + auto valueIsComplete = (pairIsComplete.second + ? std::move(pairIsComplete.first) + : service::ModifiedArgument::require("isComplete", defaultValue)); + auto valueClientMutationId = service::ModifiedArgument::require("clientMutationId", value); + + return today::CompleteTaskInput { + std::move(valueId), + valueTestTaskState, + std::move(valueIsComplete), + std::move(valueClientMutationId) + }; +} + +template <> +today::ThirdNestedInput Argument::convert(const response::Value& value) +{ + auto valueId = service::ModifiedArgument::require("id", value); + auto valueSecond = service::ModifiedArgument::require("second", value); + + return today::ThirdNestedInput { + std::move(valueId), + std::move(valueSecond) + }; +} + +template <> +today::FourthNestedInput Argument::convert(const response::Value& value) +{ + auto valueId = service::ModifiedArgument::require("id", value); + + return today::FourthNestedInput { + std::move(valueId) + }; +} + +template <> +today::IncludeNullableSelfInput Argument::convert(const response::Value& value) +{ + auto valueSelf = service::ModifiedArgument::require("self", value); + + return today::IncludeNullableSelfInput { + std::move(valueSelf) + }; +} + +template <> +today::IncludeNonNullableListSelfInput Argument::convert(const response::Value& value) +{ + auto valueSelves = service::ModifiedArgument::require("selves", value); + + return today::IncludeNonNullableListSelfInput { + std::move(valueSelves) + }; +} + +template <> +today::StringOperationFilterInput Argument::convert(const response::Value& value) +{ + auto valueAnd_ = service::ModifiedArgument::require("and", value); + auto valueOr_ = service::ModifiedArgument::require("or", value); + auto valueEqual = service::ModifiedArgument::require("equal", value); + auto valueNotEqual = service::ModifiedArgument::require("notEqual", value); + auto valueContains = service::ModifiedArgument::require("contains", value); + auto valueNotContains = service::ModifiedArgument::require("notContains", value); + auto valueIn = service::ModifiedArgument::require("in", value); + auto valueNotIn = service::ModifiedArgument::require("notIn", value); + auto valueStartsWith = service::ModifiedArgument::require("startsWith", value); + auto valueNotStartsWith = service::ModifiedArgument::require("notStartsWith", value); + auto valueEndsWith = service::ModifiedArgument::require("endsWith", value); + auto valueNotEndsWith = service::ModifiedArgument::require("notEndsWith", value); + + return today::StringOperationFilterInput { + std::move(valueAnd_), + std::move(valueOr_), + std::move(valueEqual), + std::move(valueNotEqual), + std::move(valueContains), + std::move(valueNotContains), + std::move(valueIn), + std::move(valueNotIn), + std::move(valueStartsWith), + std::move(valueNotStartsWith), + std::move(valueEndsWith), + std::move(valueNotEndsWith) + }; +} + +template <> +today::SecondNestedInput Argument::convert(const response::Value& value) +{ + auto valueId = service::ModifiedArgument::require("id", value); + auto valueThird = service::ModifiedArgument::require("third", value); + + return today::SecondNestedInput { + std::move(valueId), + std::move(valueThird) + }; +} + +template <> +today::ForwardDeclaredInput Argument::convert(const response::Value& value) +{ + auto valueNullableSelf = service::ModifiedArgument::require("nullableSelf", value); + auto valueListSelves = service::ModifiedArgument::require("listSelves", value); + + return today::ForwardDeclaredInput { + std::move(valueNullableSelf), + std::move(valueListSelves) + }; +} + +template <> +today::FirstNestedInput Argument::convert(const response::Value& value) +{ + auto valueId = service::ModifiedArgument::require("id", value); + auto valueSecond = service::ModifiedArgument::require("second", value); + auto valueThird = service::ModifiedArgument::require("third", value); + + return today::FirstNestedInput { + std::move(valueId), + std::move(valueSecond), + std::move(valueThird) + }; +} + +} // namespace service + +namespace today { + +CompleteTaskInput::CompleteTaskInput() noexcept + : id {} + , testTaskState {} + , isComplete {} + , clientMutationId {} +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +CompleteTaskInput::CompleteTaskInput( + response::IdType idArg, + std::optional testTaskStateArg, + std::optional isCompleteArg, + std::optional clientMutationIdArg) noexcept + : id { std::move(idArg) } + , testTaskState { std::move(testTaskStateArg) } + , isComplete { std::move(isCompleteArg) } + , clientMutationId { std::move(clientMutationIdArg) } +{ +} + +CompleteTaskInput::CompleteTaskInput(const CompleteTaskInput& other) + : id { service::ModifiedArgument::duplicate(other.id) } + , testTaskState { service::ModifiedArgument::duplicate(other.testTaskState) } + , isComplete { service::ModifiedArgument::duplicate(other.isComplete) } + , clientMutationId { service::ModifiedArgument::duplicate(other.clientMutationId) } +{ +} + +CompleteTaskInput::CompleteTaskInput(CompleteTaskInput&& other) noexcept + : id { std::move(other.id) } + , testTaskState { std::move(other.testTaskState) } + , isComplete { std::move(other.isComplete) } + , clientMutationId { std::move(other.clientMutationId) } +{ +} + +CompleteTaskInput::~CompleteTaskInput() +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +CompleteTaskInput& CompleteTaskInput::operator=(const CompleteTaskInput& other) +{ + CompleteTaskInput value { other }; + + std::swap(*this, value); + + return *this; +} + +CompleteTaskInput& CompleteTaskInput::operator=(CompleteTaskInput&& other) noexcept +{ + id = std::move(other.id); + testTaskState = std::move(other.testTaskState); + isComplete = std::move(other.isComplete); + clientMutationId = std::move(other.clientMutationId); + + return *this; +} + + +ThirdNestedInput::ThirdNestedInput() noexcept + : id {} + , second {} +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +ThirdNestedInput::ThirdNestedInput( + response::IdType idArg, + std::unique_ptr secondArg) noexcept + : id { std::move(idArg) } + , second { std::move(secondArg) } +{ +} + +ThirdNestedInput::ThirdNestedInput(const ThirdNestedInput& other) + : id { service::ModifiedArgument::duplicate(other.id) } + , second { service::ModifiedArgument::duplicate(other.second) } +{ +} + +ThirdNestedInput::ThirdNestedInput(ThirdNestedInput&& other) noexcept + : id { std::move(other.id) } + , second { std::move(other.second) } +{ +} + +ThirdNestedInput::~ThirdNestedInput() +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +ThirdNestedInput& ThirdNestedInput::operator=(const ThirdNestedInput& other) +{ + ThirdNestedInput value { other }; + + std::swap(*this, value); + + return *this; +} + +ThirdNestedInput& ThirdNestedInput::operator=(ThirdNestedInput&& other) noexcept +{ + id = std::move(other.id); + second = std::move(other.second); + + return *this; +} + + +FourthNestedInput::FourthNestedInput() noexcept + : id {} +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +FourthNestedInput::FourthNestedInput( + response::IdType idArg) noexcept + : id { std::move(idArg) } +{ +} + +FourthNestedInput::FourthNestedInput(const FourthNestedInput& other) + : id { service::ModifiedArgument::duplicate(other.id) } +{ +} + +FourthNestedInput::FourthNestedInput(FourthNestedInput&& other) noexcept + : id { std::move(other.id) } +{ +} + +FourthNestedInput::~FourthNestedInput() +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +FourthNestedInput& FourthNestedInput::operator=(const FourthNestedInput& other) +{ + FourthNestedInput value { other }; + + std::swap(*this, value); + + return *this; +} + +FourthNestedInput& FourthNestedInput::operator=(FourthNestedInput&& other) noexcept +{ + id = std::move(other.id); + + return *this; +} + + +IncludeNullableSelfInput::IncludeNullableSelfInput() noexcept + : self {} +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +IncludeNullableSelfInput::IncludeNullableSelfInput( + std::unique_ptr selfArg) noexcept + : self { std::move(selfArg) } +{ +} + +IncludeNullableSelfInput::IncludeNullableSelfInput(const IncludeNullableSelfInput& other) + : self { service::ModifiedArgument::duplicate(other.self) } +{ +} + +IncludeNullableSelfInput::IncludeNullableSelfInput(IncludeNullableSelfInput&& other) noexcept + : self { std::move(other.self) } +{ +} + +IncludeNullableSelfInput::~IncludeNullableSelfInput() +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +IncludeNullableSelfInput& IncludeNullableSelfInput::operator=(const IncludeNullableSelfInput& other) +{ + IncludeNullableSelfInput value { other }; + + std::swap(*this, value); + + return *this; +} + +IncludeNullableSelfInput& IncludeNullableSelfInput::operator=(IncludeNullableSelfInput&& other) noexcept +{ + self = std::move(other.self); + + return *this; +} + + +IncludeNonNullableListSelfInput::IncludeNonNullableListSelfInput() noexcept + : selves {} +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +IncludeNonNullableListSelfInput::IncludeNonNullableListSelfInput( + std::vector selvesArg) noexcept + : selves { std::move(selvesArg) } +{ +} + +IncludeNonNullableListSelfInput::IncludeNonNullableListSelfInput(const IncludeNonNullableListSelfInput& other) + : selves { service::ModifiedArgument::duplicate(other.selves) } +{ +} + +IncludeNonNullableListSelfInput::IncludeNonNullableListSelfInput(IncludeNonNullableListSelfInput&& other) noexcept + : selves { std::move(other.selves) } +{ +} + +IncludeNonNullableListSelfInput::~IncludeNonNullableListSelfInput() +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +IncludeNonNullableListSelfInput& IncludeNonNullableListSelfInput::operator=(const IncludeNonNullableListSelfInput& other) +{ + IncludeNonNullableListSelfInput value { other }; + + std::swap(*this, value); + + return *this; +} + +IncludeNonNullableListSelfInput& IncludeNonNullableListSelfInput::operator=(IncludeNonNullableListSelfInput&& other) noexcept +{ + selves = std::move(other.selves); + + return *this; +} + + +StringOperationFilterInput::StringOperationFilterInput() noexcept + : and_ {} + , or_ {} + , equal {} + , notEqual {} + , contains {} + , notContains {} + , in {} + , notIn {} + , startsWith {} + , notStartsWith {} + , endsWith {} + , notEndsWith {} +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +StringOperationFilterInput::StringOperationFilterInput( + std::optional> and_Arg, + std::optional> or_Arg, + std::optional equalArg, + std::optional notEqualArg, + std::optional containsArg, + std::optional notContainsArg, + std::optional> inArg, + std::optional> notInArg, + std::optional startsWithArg, + std::optional notStartsWithArg, + std::optional endsWithArg, + std::optional notEndsWithArg) noexcept + : and_ { std::move(and_Arg) } + , or_ { std::move(or_Arg) } + , equal { std::move(equalArg) } + , notEqual { std::move(notEqualArg) } + , contains { std::move(containsArg) } + , notContains { std::move(notContainsArg) } + , in { std::move(inArg) } + , notIn { std::move(notInArg) } + , startsWith { std::move(startsWithArg) } + , notStartsWith { std::move(notStartsWithArg) } + , endsWith { std::move(endsWithArg) } + , notEndsWith { std::move(notEndsWithArg) } +{ +} + +StringOperationFilterInput::StringOperationFilterInput(const StringOperationFilterInput& other) + : and_ { service::ModifiedArgument::duplicate(other.and_) } + , or_ { service::ModifiedArgument::duplicate(other.or_) } + , equal { service::ModifiedArgument::duplicate(other.equal) } + , notEqual { service::ModifiedArgument::duplicate(other.notEqual) } + , contains { service::ModifiedArgument::duplicate(other.contains) } + , notContains { service::ModifiedArgument::duplicate(other.notContains) } + , in { service::ModifiedArgument::duplicate(other.in) } + , notIn { service::ModifiedArgument::duplicate(other.notIn) } + , startsWith { service::ModifiedArgument::duplicate(other.startsWith) } + , notStartsWith { service::ModifiedArgument::duplicate(other.notStartsWith) } + , endsWith { service::ModifiedArgument::duplicate(other.endsWith) } + , notEndsWith { service::ModifiedArgument::duplicate(other.notEndsWith) } +{ +} + +StringOperationFilterInput::StringOperationFilterInput(StringOperationFilterInput&& other) noexcept + : and_ { std::move(other.and_) } + , or_ { std::move(other.or_) } + , equal { std::move(other.equal) } + , notEqual { std::move(other.notEqual) } + , contains { std::move(other.contains) } + , notContains { std::move(other.notContains) } + , in { std::move(other.in) } + , notIn { std::move(other.notIn) } + , startsWith { std::move(other.startsWith) } + , notStartsWith { std::move(other.notStartsWith) } + , endsWith { std::move(other.endsWith) } + , notEndsWith { std::move(other.notEndsWith) } +{ +} + +StringOperationFilterInput::~StringOperationFilterInput() +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +StringOperationFilterInput& StringOperationFilterInput::operator=(const StringOperationFilterInput& other) +{ + StringOperationFilterInput value { other }; + + std::swap(*this, value); + + return *this; +} + +StringOperationFilterInput& StringOperationFilterInput::operator=(StringOperationFilterInput&& other) noexcept +{ + and_ = std::move(other.and_); + or_ = std::move(other.or_); + equal = std::move(other.equal); + notEqual = std::move(other.notEqual); + contains = std::move(other.contains); + notContains = std::move(other.notContains); + in = std::move(other.in); + notIn = std::move(other.notIn); + startsWith = std::move(other.startsWith); + notStartsWith = std::move(other.notStartsWith); + endsWith = std::move(other.endsWith); + notEndsWith = std::move(other.notEndsWith); + + return *this; +} + + +SecondNestedInput::SecondNestedInput() noexcept + : id {} + , third {} +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +SecondNestedInput::SecondNestedInput( + response::IdType idArg, + ThirdNestedInput thirdArg) noexcept + : id { std::move(idArg) } + , third { std::move(thirdArg) } +{ +} + +SecondNestedInput::SecondNestedInput(const SecondNestedInput& other) + : id { service::ModifiedArgument::duplicate(other.id) } + , third { service::ModifiedArgument::duplicate(other.third) } +{ +} + +SecondNestedInput::SecondNestedInput(SecondNestedInput&& other) noexcept + : id { std::move(other.id) } + , third { std::move(other.third) } +{ +} + +SecondNestedInput::~SecondNestedInput() +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +SecondNestedInput& SecondNestedInput::operator=(const SecondNestedInput& other) +{ + SecondNestedInput value { other }; + + std::swap(*this, value); + + return *this; +} + +SecondNestedInput& SecondNestedInput::operator=(SecondNestedInput&& other) noexcept +{ + id = std::move(other.id); + third = std::move(other.third); + + return *this; +} + + +ForwardDeclaredInput::ForwardDeclaredInput() noexcept + : nullableSelf {} + , listSelves {} +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +ForwardDeclaredInput::ForwardDeclaredInput( + std::unique_ptr nullableSelfArg, + IncludeNonNullableListSelfInput listSelvesArg) noexcept + : nullableSelf { std::move(nullableSelfArg) } + , listSelves { std::move(listSelvesArg) } +{ +} + +ForwardDeclaredInput::ForwardDeclaredInput(const ForwardDeclaredInput& other) + : nullableSelf { service::ModifiedArgument::duplicate(other.nullableSelf) } + , listSelves { service::ModifiedArgument::duplicate(other.listSelves) } +{ +} + +ForwardDeclaredInput::ForwardDeclaredInput(ForwardDeclaredInput&& other) noexcept + : nullableSelf { std::move(other.nullableSelf) } + , listSelves { std::move(other.listSelves) } +{ +} + +ForwardDeclaredInput::~ForwardDeclaredInput() +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +ForwardDeclaredInput& ForwardDeclaredInput::operator=(const ForwardDeclaredInput& other) +{ + ForwardDeclaredInput value { other }; + + std::swap(*this, value); + + return *this; +} + +ForwardDeclaredInput& ForwardDeclaredInput::operator=(ForwardDeclaredInput&& other) noexcept +{ + nullableSelf = std::move(other.nullableSelf); + listSelves = std::move(other.listSelves); + + return *this; +} + + +FirstNestedInput::FirstNestedInput() noexcept + : id {} + , second {} + , third {} +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +FirstNestedInput::FirstNestedInput( + response::IdType idArg, + SecondNestedInput secondArg, + ThirdNestedInput thirdArg) noexcept + : id { std::move(idArg) } + , second { std::move(secondArg) } + , third { std::move(thirdArg) } +{ +} + +FirstNestedInput::FirstNestedInput(const FirstNestedInput& other) + : id { service::ModifiedArgument::duplicate(other.id) } + , second { service::ModifiedArgument::duplicate(other.second) } + , third { service::ModifiedArgument::duplicate(other.third) } +{ +} + +FirstNestedInput::FirstNestedInput(FirstNestedInput&& other) noexcept + : id { std::move(other.id) } + , second { std::move(other.second) } + , third { std::move(other.third) } +{ +} + +FirstNestedInput::~FirstNestedInput() +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +FirstNestedInput& FirstNestedInput::operator=(const FirstNestedInput& other) +{ + FirstNestedInput value { other }; + + std::swap(*this, value); + + return *this; +} + +FirstNestedInput& FirstNestedInput::operator=(FirstNestedInput&& other) noexcept +{ + id = std::move(other.id); + second = std::move(other.second); + third = std::move(other.third); + + return *this; +} + +} // namespace today +} // namespace graphql diff --git a/samples/today/nointrospection/TodaySharedTypes.h b/samples/today/nointrospection/TodaySharedTypes.h new file mode 100644 index 00000000..b3c7b086 --- /dev/null +++ b/samples/today/nointrospection/TodaySharedTypes.h @@ -0,0 +1,239 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// WARNING! Do not edit this file manually, your changes will be overwritten. + +#pragma once + +#ifndef TODAYSHAREDTYPES_H +#define TODAYSHAREDTYPES_H + +#include "graphqlservice/GraphQLResponse.h" + +#include "graphqlservice/internal/Version.h" + +#include +#include +#include +#include +#include +#include + +// Check if the library version is compatible with schemagen 5.0.0 +static_assert(graphql::internal::MajorVersion == 5, "regenerate with schemagen: major version mismatch"); +static_assert(graphql::internal::MinorVersion == 0, "regenerate with schemagen: minor version mismatch"); + +namespace graphql { +namespace today { + +enum class [[nodiscard("unnecessary conversion")]] TaskState +{ + Unassigned, + New, + Started, + Complete +}; + +[[nodiscard("unnecessary call")]] constexpr auto getTaskStateNames() noexcept +{ + using namespace std::literals; + + return std::array { + R"gql(Unassigned)gql"sv, + R"gql(New)gql"sv, + R"gql(Started)gql"sv, + R"gql(Complete)gql"sv + }; +} + +[[nodiscard("unnecessary call")]] constexpr auto getTaskStateValues() noexcept +{ + using namespace std::literals; + + return std::array, 4> { + std::make_pair(R"gql(New)gql"sv, TaskState::New), + std::make_pair(R"gql(Started)gql"sv, TaskState::Started), + std::make_pair(R"gql(Complete)gql"sv, TaskState::Complete), + std::make_pair(R"gql(Unassigned)gql"sv, TaskState::Unassigned) + }; +} + +struct [[nodiscard("unnecessary construction")]] CompleteTaskInput +{ + explicit CompleteTaskInput() noexcept; + explicit CompleteTaskInput( + response::IdType idArg, + std::optional testTaskStateArg, + std::optional isCompleteArg, + std::optional clientMutationIdArg) noexcept; + CompleteTaskInput(const CompleteTaskInput& other); + CompleteTaskInput(CompleteTaskInput&& other) noexcept; + ~CompleteTaskInput(); + + CompleteTaskInput& operator=(const CompleteTaskInput& other); + CompleteTaskInput& operator=(CompleteTaskInput&& other) noexcept; + + response::IdType id; + std::optional testTaskState; + std::optional isComplete; + std::optional clientMutationId; +}; + +struct SecondNestedInput; + +struct [[nodiscard("unnecessary construction")]] ThirdNestedInput +{ + explicit ThirdNestedInput() noexcept; + explicit ThirdNestedInput( + response::IdType idArg, + std::unique_ptr secondArg) noexcept; + ThirdNestedInput(const ThirdNestedInput& other); + ThirdNestedInput(ThirdNestedInput&& other) noexcept; + ~ThirdNestedInput(); + + ThirdNestedInput& operator=(const ThirdNestedInput& other); + ThirdNestedInput& operator=(ThirdNestedInput&& other) noexcept; + + response::IdType id; + std::unique_ptr second; +}; + +struct [[nodiscard("unnecessary construction")]] FourthNestedInput +{ + explicit FourthNestedInput() noexcept; + explicit FourthNestedInput( + response::IdType idArg) noexcept; + FourthNestedInput(const FourthNestedInput& other); + FourthNestedInput(FourthNestedInput&& other) noexcept; + ~FourthNestedInput(); + + FourthNestedInput& operator=(const FourthNestedInput& other); + FourthNestedInput& operator=(FourthNestedInput&& other) noexcept; + + response::IdType id; +}; + +struct [[nodiscard("unnecessary construction")]] IncludeNullableSelfInput +{ + explicit IncludeNullableSelfInput() noexcept; + explicit IncludeNullableSelfInput( + std::unique_ptr selfArg) noexcept; + IncludeNullableSelfInput(const IncludeNullableSelfInput& other); + IncludeNullableSelfInput(IncludeNullableSelfInput&& other) noexcept; + ~IncludeNullableSelfInput(); + + IncludeNullableSelfInput& operator=(const IncludeNullableSelfInput& other); + IncludeNullableSelfInput& operator=(IncludeNullableSelfInput&& other) noexcept; + + std::unique_ptr self; +}; + +struct [[nodiscard("unnecessary construction")]] IncludeNonNullableListSelfInput +{ + explicit IncludeNonNullableListSelfInput() noexcept; + explicit IncludeNonNullableListSelfInput( + std::vector selvesArg) noexcept; + IncludeNonNullableListSelfInput(const IncludeNonNullableListSelfInput& other); + IncludeNonNullableListSelfInput(IncludeNonNullableListSelfInput&& other) noexcept; + ~IncludeNonNullableListSelfInput(); + + IncludeNonNullableListSelfInput& operator=(const IncludeNonNullableListSelfInput& other); + IncludeNonNullableListSelfInput& operator=(IncludeNonNullableListSelfInput&& other) noexcept; + + std::vector selves; +}; + +struct [[nodiscard("unnecessary construction")]] StringOperationFilterInput +{ + explicit StringOperationFilterInput() noexcept; + explicit StringOperationFilterInput( + std::optional> and_Arg, + std::optional> or_Arg, + std::optional equalArg, + std::optional notEqualArg, + std::optional containsArg, + std::optional notContainsArg, + std::optional> inArg, + std::optional> notInArg, + std::optional startsWithArg, + std::optional notStartsWithArg, + std::optional endsWithArg, + std::optional notEndsWithArg) noexcept; + StringOperationFilterInput(const StringOperationFilterInput& other); + StringOperationFilterInput(StringOperationFilterInput&& other) noexcept; + ~StringOperationFilterInput(); + + StringOperationFilterInput& operator=(const StringOperationFilterInput& other); + StringOperationFilterInput& operator=(StringOperationFilterInput&& other) noexcept; + + std::optional> and_; + std::optional> or_; + std::optional equal; + std::optional notEqual; + std::optional contains; + std::optional notContains; + std::optional> in; + std::optional> notIn; + std::optional startsWith; + std::optional notStartsWith; + std::optional endsWith; + std::optional notEndsWith; +}; + +struct [[nodiscard("unnecessary construction")]] SecondNestedInput +{ + explicit SecondNestedInput() noexcept; + explicit SecondNestedInput( + response::IdType idArg, + ThirdNestedInput thirdArg) noexcept; + SecondNestedInput(const SecondNestedInput& other); + SecondNestedInput(SecondNestedInput&& other) noexcept; + ~SecondNestedInput(); + + SecondNestedInput& operator=(const SecondNestedInput& other); + SecondNestedInput& operator=(SecondNestedInput&& other) noexcept; + + response::IdType id; + ThirdNestedInput third; +}; + +struct [[nodiscard("unnecessary construction")]] ForwardDeclaredInput +{ + explicit ForwardDeclaredInput() noexcept; + explicit ForwardDeclaredInput( + std::unique_ptr nullableSelfArg, + IncludeNonNullableListSelfInput listSelvesArg) noexcept; + ForwardDeclaredInput(const ForwardDeclaredInput& other); + ForwardDeclaredInput(ForwardDeclaredInput&& other) noexcept; + ~ForwardDeclaredInput(); + + ForwardDeclaredInput& operator=(const ForwardDeclaredInput& other); + ForwardDeclaredInput& operator=(ForwardDeclaredInput&& other) noexcept; + + std::unique_ptr nullableSelf; + IncludeNonNullableListSelfInput listSelves; +}; + +struct [[nodiscard("unnecessary construction")]] FirstNestedInput +{ + explicit FirstNestedInput() noexcept; + explicit FirstNestedInput( + response::IdType idArg, + SecondNestedInput secondArg, + ThirdNestedInput thirdArg) noexcept; + FirstNestedInput(const FirstNestedInput& other); + FirstNestedInput(FirstNestedInput&& other) noexcept; + ~FirstNestedInput(); + + FirstNestedInput& operator=(const FirstNestedInput& other); + FirstNestedInput& operator=(FirstNestedInput&& other) noexcept; + + response::IdType id; + SecondNestedInput second; + ThirdNestedInput third; +}; + +} // namespace today +} // namespace graphql + +#endif // TODAYSHAREDTYPES_H diff --git a/samples/today/nointrospection/TodaySharedTypes.ixx b/samples/today/nointrospection/TodaySharedTypes.ixx new file mode 100644 index 00000000..ee76a95a --- /dev/null +++ b/samples/today/nointrospection/TodaySharedTypes.ixx @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// WARNING! Do not edit this file manually, your changes will be overwritten. + +module; + +#include "TodaySharedTypes.h" + +export module GraphQL.Today.TodaySharedTypes; + +export namespace graphql::today { + +using today::TaskState; +using today::getTaskStateNames; +using today::getTaskStateValues; + +using today::CompleteTaskInput; +using today::ThirdNestedInput; +using today::FourthNestedInput; +using today::IncludeNullableSelfInput; +using today::IncludeNonNullableListSelfInput; +using today::StringOperationFilterInput; +using today::SecondNestedInput; +using today::ForwardDeclaredInput; +using today::FirstNestedInput; + +} // namespace graphql::today diff --git a/samples/today/nointrospection/today_nointrospection_schema_files b/samples/today/nointrospection/today_nointrospection_schema_files index a9ed9ecf..2e24cdcf 100644 --- a/samples/today/nointrospection/today_nointrospection_schema_files +++ b/samples/today/nointrospection/today_nointrospection_schema_files @@ -1,3 +1,4 @@ +TodaySharedTypes.cpp TodaySchema.cpp NodeObject.cpp UnionTypeObject.cpp diff --git a/samples/today/schema/TodaySchema.cpp b/samples/today/schema/TodaySchema.cpp index f55a0831..7436b7fa 100644 --- a/samples/today/schema/TodaySchema.cpp +++ b/samples/today/schema/TodaySchema.cpp @@ -22,711 +22,7 @@ using namespace std::literals; -namespace graphql { -namespace service { - -static const auto s_namesTaskState = today::getTaskStateNames(); -static const auto s_valuesTaskState = today::getTaskStateValues(); - -template <> -today::TaskState Argument::convert(const response::Value& value) -{ - if (!value.maybe_enum()) - { - throw service::schema_exception { { R"ex(not a valid TaskState value)ex" } }; - } - - const auto result = internal::sorted_map_lookup( - s_valuesTaskState, - std::string_view { value.get() }); - - if (!result) - { - throw service::schema_exception { { R"ex(not a valid TaskState value)ex" } }; - } - - return *result; -} - -template <> -service::AwaitableResolver Result::convert(service::AwaitableScalar result, ResolverParams&& params) -{ - return ModifiedResult::resolve(std::move(result), std::move(params), - [](today::TaskState value, const ResolverParams&) - { - response::Value resolvedResult(response::Type::EnumValue); - - resolvedResult.set(std::string { s_namesTaskState[static_cast(value)] }); - - return resolvedResult; - }); -} - -template <> -void Result::validateScalar(const response::Value& value) -{ - if (!value.maybe_enum()) - { - throw service::schema_exception { { R"ex(not a valid TaskState value)ex" } }; - } - - const auto [itr, itrEnd] = internal::sorted_map_equal_range( - s_valuesTaskState.begin(), - s_valuesTaskState.end(), - std::string_view { value.get() }); - - if (itr == itrEnd) - { - throw service::schema_exception { { R"ex(not a valid TaskState value)ex" } }; - } -} - -template <> -today::CompleteTaskInput Argument::convert(const response::Value& value) -{ - const auto defaultValue = []() - { - response::Value values(response::Type::Map); - response::Value entry; - - entry = response::Value(true); - values.emplace_back("isComplete", std::move(entry)); - - return values; - }(); - - auto valueId = service::ModifiedArgument::require("id", value); - auto valueTestTaskState = service::ModifiedArgument::require("testTaskState", value); - auto pairIsComplete = service::ModifiedArgument::find("isComplete", value); - auto valueIsComplete = (pairIsComplete.second - ? std::move(pairIsComplete.first) - : service::ModifiedArgument::require("isComplete", defaultValue)); - auto valueClientMutationId = service::ModifiedArgument::require("clientMutationId", value); - - return today::CompleteTaskInput { - std::move(valueId), - valueTestTaskState, - std::move(valueIsComplete), - std::move(valueClientMutationId) - }; -} - -template <> -today::ThirdNestedInput Argument::convert(const response::Value& value) -{ - auto valueId = service::ModifiedArgument::require("id", value); - auto valueSecond = service::ModifiedArgument::require("second", value); - - return today::ThirdNestedInput { - std::move(valueId), - std::move(valueSecond) - }; -} - -template <> -today::FourthNestedInput Argument::convert(const response::Value& value) -{ - auto valueId = service::ModifiedArgument::require("id", value); - - return today::FourthNestedInput { - std::move(valueId) - }; -} - -template <> -today::IncludeNullableSelfInput Argument::convert(const response::Value& value) -{ - auto valueSelf = service::ModifiedArgument::require("self", value); - - return today::IncludeNullableSelfInput { - std::move(valueSelf) - }; -} - -template <> -today::IncludeNonNullableListSelfInput Argument::convert(const response::Value& value) -{ - auto valueSelves = service::ModifiedArgument::require("selves", value); - - return today::IncludeNonNullableListSelfInput { - std::move(valueSelves) - }; -} - -template <> -today::StringOperationFilterInput Argument::convert(const response::Value& value) -{ - auto valueAnd_ = service::ModifiedArgument::require("and", value); - auto valueOr_ = service::ModifiedArgument::require("or", value); - auto valueEqual = service::ModifiedArgument::require("equal", value); - auto valueNotEqual = service::ModifiedArgument::require("notEqual", value); - auto valueContains = service::ModifiedArgument::require("contains", value); - auto valueNotContains = service::ModifiedArgument::require("notContains", value); - auto valueIn = service::ModifiedArgument::require("in", value); - auto valueNotIn = service::ModifiedArgument::require("notIn", value); - auto valueStartsWith = service::ModifiedArgument::require("startsWith", value); - auto valueNotStartsWith = service::ModifiedArgument::require("notStartsWith", value); - auto valueEndsWith = service::ModifiedArgument::require("endsWith", value); - auto valueNotEndsWith = service::ModifiedArgument::require("notEndsWith", value); - - return today::StringOperationFilterInput { - std::move(valueAnd_), - std::move(valueOr_), - std::move(valueEqual), - std::move(valueNotEqual), - std::move(valueContains), - std::move(valueNotContains), - std::move(valueIn), - std::move(valueNotIn), - std::move(valueStartsWith), - std::move(valueNotStartsWith), - std::move(valueEndsWith), - std::move(valueNotEndsWith) - }; -} - -template <> -today::SecondNestedInput Argument::convert(const response::Value& value) -{ - auto valueId = service::ModifiedArgument::require("id", value); - auto valueThird = service::ModifiedArgument::require("third", value); - - return today::SecondNestedInput { - std::move(valueId), - std::move(valueThird) - }; -} - -template <> -today::ForwardDeclaredInput Argument::convert(const response::Value& value) -{ - auto valueNullableSelf = service::ModifiedArgument::require("nullableSelf", value); - auto valueListSelves = service::ModifiedArgument::require("listSelves", value); - - return today::ForwardDeclaredInput { - std::move(valueNullableSelf), - std::move(valueListSelves) - }; -} - -template <> -today::FirstNestedInput Argument::convert(const response::Value& value) -{ - auto valueId = service::ModifiedArgument::require("id", value); - auto valueSecond = service::ModifiedArgument::require("second", value); - auto valueThird = service::ModifiedArgument::require("third", value); - - return today::FirstNestedInput { - std::move(valueId), - std::move(valueSecond), - std::move(valueThird) - }; -} - -} // namespace service - -namespace today { - -CompleteTaskInput::CompleteTaskInput() noexcept - : id {} - , testTaskState {} - , isComplete {} - , clientMutationId {} -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -CompleteTaskInput::CompleteTaskInput( - response::IdType idArg, - std::optional testTaskStateArg, - std::optional isCompleteArg, - std::optional clientMutationIdArg) noexcept - : id { std::move(idArg) } - , testTaskState { std::move(testTaskStateArg) } - , isComplete { std::move(isCompleteArg) } - , clientMutationId { std::move(clientMutationIdArg) } -{ -} - -CompleteTaskInput::CompleteTaskInput(const CompleteTaskInput& other) - : id { service::ModifiedArgument::duplicate(other.id) } - , testTaskState { service::ModifiedArgument::duplicate(other.testTaskState) } - , isComplete { service::ModifiedArgument::duplicate(other.isComplete) } - , clientMutationId { service::ModifiedArgument::duplicate(other.clientMutationId) } -{ -} - -CompleteTaskInput::CompleteTaskInput(CompleteTaskInput&& other) noexcept - : id { std::move(other.id) } - , testTaskState { std::move(other.testTaskState) } - , isComplete { std::move(other.isComplete) } - , clientMutationId { std::move(other.clientMutationId) } -{ -} - -CompleteTaskInput::~CompleteTaskInput() -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -CompleteTaskInput& CompleteTaskInput::operator=(const CompleteTaskInput& other) -{ - CompleteTaskInput value { other }; - - std::swap(*this, value); - - return *this; -} - -CompleteTaskInput& CompleteTaskInput::operator=(CompleteTaskInput&& other) noexcept -{ - id = std::move(other.id); - testTaskState = std::move(other.testTaskState); - isComplete = std::move(other.isComplete); - clientMutationId = std::move(other.clientMutationId); - - return *this; -} - -ThirdNestedInput::ThirdNestedInput() noexcept - : id {} - , second {} -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -ThirdNestedInput::ThirdNestedInput( - response::IdType idArg, - std::unique_ptr secondArg) noexcept - : id { std::move(idArg) } - , second { std::move(secondArg) } -{ -} - -ThirdNestedInput::ThirdNestedInput(const ThirdNestedInput& other) - : id { service::ModifiedArgument::duplicate(other.id) } - , second { service::ModifiedArgument::duplicate(other.second) } -{ -} - -ThirdNestedInput::ThirdNestedInput(ThirdNestedInput&& other) noexcept - : id { std::move(other.id) } - , second { std::move(other.second) } -{ -} - -ThirdNestedInput::~ThirdNestedInput() -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -ThirdNestedInput& ThirdNestedInput::operator=(const ThirdNestedInput& other) -{ - ThirdNestedInput value { other }; - - std::swap(*this, value); - - return *this; -} - -ThirdNestedInput& ThirdNestedInput::operator=(ThirdNestedInput&& other) noexcept -{ - id = std::move(other.id); - second = std::move(other.second); - - return *this; -} - -FourthNestedInput::FourthNestedInput() noexcept - : id {} -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -FourthNestedInput::FourthNestedInput( - response::IdType idArg) noexcept - : id { std::move(idArg) } -{ -} - -FourthNestedInput::FourthNestedInput(const FourthNestedInput& other) - : id { service::ModifiedArgument::duplicate(other.id) } -{ -} - -FourthNestedInput::FourthNestedInput(FourthNestedInput&& other) noexcept - : id { std::move(other.id) } -{ -} - -FourthNestedInput::~FourthNestedInput() -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -FourthNestedInput& FourthNestedInput::operator=(const FourthNestedInput& other) -{ - FourthNestedInput value { other }; - - std::swap(*this, value); - - return *this; -} - -FourthNestedInput& FourthNestedInput::operator=(FourthNestedInput&& other) noexcept -{ - id = std::move(other.id); - - return *this; -} - -IncludeNullableSelfInput::IncludeNullableSelfInput() noexcept - : self {} -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -IncludeNullableSelfInput::IncludeNullableSelfInput( - std::unique_ptr selfArg) noexcept - : self { std::move(selfArg) } -{ -} - -IncludeNullableSelfInput::IncludeNullableSelfInput(const IncludeNullableSelfInput& other) - : self { service::ModifiedArgument::duplicate(other.self) } -{ -} - -IncludeNullableSelfInput::IncludeNullableSelfInput(IncludeNullableSelfInput&& other) noexcept - : self { std::move(other.self) } -{ -} - -IncludeNullableSelfInput::~IncludeNullableSelfInput() -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -IncludeNullableSelfInput& IncludeNullableSelfInput::operator=(const IncludeNullableSelfInput& other) -{ - IncludeNullableSelfInput value { other }; - - std::swap(*this, value); - - return *this; -} - -IncludeNullableSelfInput& IncludeNullableSelfInput::operator=(IncludeNullableSelfInput&& other) noexcept -{ - self = std::move(other.self); - - return *this; -} - -IncludeNonNullableListSelfInput::IncludeNonNullableListSelfInput() noexcept - : selves {} -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -IncludeNonNullableListSelfInput::IncludeNonNullableListSelfInput( - std::vector selvesArg) noexcept - : selves { std::move(selvesArg) } -{ -} - -IncludeNonNullableListSelfInput::IncludeNonNullableListSelfInput(const IncludeNonNullableListSelfInput& other) - : selves { service::ModifiedArgument::duplicate(other.selves) } -{ -} - -IncludeNonNullableListSelfInput::IncludeNonNullableListSelfInput(IncludeNonNullableListSelfInput&& other) noexcept - : selves { std::move(other.selves) } -{ -} - -IncludeNonNullableListSelfInput::~IncludeNonNullableListSelfInput() -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -IncludeNonNullableListSelfInput& IncludeNonNullableListSelfInput::operator=(const IncludeNonNullableListSelfInput& other) -{ - IncludeNonNullableListSelfInput value { other }; - - std::swap(*this, value); - - return *this; -} - -IncludeNonNullableListSelfInput& IncludeNonNullableListSelfInput::operator=(IncludeNonNullableListSelfInput&& other) noexcept -{ - selves = std::move(other.selves); - - return *this; -} - -StringOperationFilterInput::StringOperationFilterInput() noexcept - : and_ {} - , or_ {} - , equal {} - , notEqual {} - , contains {} - , notContains {} - , in {} - , notIn {} - , startsWith {} - , notStartsWith {} - , endsWith {} - , notEndsWith {} -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -StringOperationFilterInput::StringOperationFilterInput( - std::optional> and_Arg, - std::optional> or_Arg, - std::optional equalArg, - std::optional notEqualArg, - std::optional containsArg, - std::optional notContainsArg, - std::optional> inArg, - std::optional> notInArg, - std::optional startsWithArg, - std::optional notStartsWithArg, - std::optional endsWithArg, - std::optional notEndsWithArg) noexcept - : and_ { std::move(and_Arg) } - , or_ { std::move(or_Arg) } - , equal { std::move(equalArg) } - , notEqual { std::move(notEqualArg) } - , contains { std::move(containsArg) } - , notContains { std::move(notContainsArg) } - , in { std::move(inArg) } - , notIn { std::move(notInArg) } - , startsWith { std::move(startsWithArg) } - , notStartsWith { std::move(notStartsWithArg) } - , endsWith { std::move(endsWithArg) } - , notEndsWith { std::move(notEndsWithArg) } -{ -} - -StringOperationFilterInput::StringOperationFilterInput(const StringOperationFilterInput& other) - : and_ { service::ModifiedArgument::duplicate(other.and_) } - , or_ { service::ModifiedArgument::duplicate(other.or_) } - , equal { service::ModifiedArgument::duplicate(other.equal) } - , notEqual { service::ModifiedArgument::duplicate(other.notEqual) } - , contains { service::ModifiedArgument::duplicate(other.contains) } - , notContains { service::ModifiedArgument::duplicate(other.notContains) } - , in { service::ModifiedArgument::duplicate(other.in) } - , notIn { service::ModifiedArgument::duplicate(other.notIn) } - , startsWith { service::ModifiedArgument::duplicate(other.startsWith) } - , notStartsWith { service::ModifiedArgument::duplicate(other.notStartsWith) } - , endsWith { service::ModifiedArgument::duplicate(other.endsWith) } - , notEndsWith { service::ModifiedArgument::duplicate(other.notEndsWith) } -{ -} - -StringOperationFilterInput::StringOperationFilterInput(StringOperationFilterInput&& other) noexcept - : and_ { std::move(other.and_) } - , or_ { std::move(other.or_) } - , equal { std::move(other.equal) } - , notEqual { std::move(other.notEqual) } - , contains { std::move(other.contains) } - , notContains { std::move(other.notContains) } - , in { std::move(other.in) } - , notIn { std::move(other.notIn) } - , startsWith { std::move(other.startsWith) } - , notStartsWith { std::move(other.notStartsWith) } - , endsWith { std::move(other.endsWith) } - , notEndsWith { std::move(other.notEndsWith) } -{ -} - -StringOperationFilterInput::~StringOperationFilterInput() -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -StringOperationFilterInput& StringOperationFilterInput::operator=(const StringOperationFilterInput& other) -{ - StringOperationFilterInput value { other }; - - std::swap(*this, value); - - return *this; -} - -StringOperationFilterInput& StringOperationFilterInput::operator=(StringOperationFilterInput&& other) noexcept -{ - and_ = std::move(other.and_); - or_ = std::move(other.or_); - equal = std::move(other.equal); - notEqual = std::move(other.notEqual); - contains = std::move(other.contains); - notContains = std::move(other.notContains); - in = std::move(other.in); - notIn = std::move(other.notIn); - startsWith = std::move(other.startsWith); - notStartsWith = std::move(other.notStartsWith); - endsWith = std::move(other.endsWith); - notEndsWith = std::move(other.notEndsWith); - - return *this; -} - -SecondNestedInput::SecondNestedInput() noexcept - : id {} - , third {} -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -SecondNestedInput::SecondNestedInput( - response::IdType idArg, - ThirdNestedInput thirdArg) noexcept - : id { std::move(idArg) } - , third { std::move(thirdArg) } -{ -} - -SecondNestedInput::SecondNestedInput(const SecondNestedInput& other) - : id { service::ModifiedArgument::duplicate(other.id) } - , third { service::ModifiedArgument::duplicate(other.third) } -{ -} - -SecondNestedInput::SecondNestedInput(SecondNestedInput&& other) noexcept - : id { std::move(other.id) } - , third { std::move(other.third) } -{ -} - -SecondNestedInput::~SecondNestedInput() -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -SecondNestedInput& SecondNestedInput::operator=(const SecondNestedInput& other) -{ - SecondNestedInput value { other }; - - std::swap(*this, value); - - return *this; -} - -SecondNestedInput& SecondNestedInput::operator=(SecondNestedInput&& other) noexcept -{ - id = std::move(other.id); - third = std::move(other.third); - - return *this; -} - -ForwardDeclaredInput::ForwardDeclaredInput() noexcept - : nullableSelf {} - , listSelves {} -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -ForwardDeclaredInput::ForwardDeclaredInput( - std::unique_ptr nullableSelfArg, - IncludeNonNullableListSelfInput listSelvesArg) noexcept - : nullableSelf { std::move(nullableSelfArg) } - , listSelves { std::move(listSelvesArg) } -{ -} - -ForwardDeclaredInput::ForwardDeclaredInput(const ForwardDeclaredInput& other) - : nullableSelf { service::ModifiedArgument::duplicate(other.nullableSelf) } - , listSelves { service::ModifiedArgument::duplicate(other.listSelves) } -{ -} - -ForwardDeclaredInput::ForwardDeclaredInput(ForwardDeclaredInput&& other) noexcept - : nullableSelf { std::move(other.nullableSelf) } - , listSelves { std::move(other.listSelves) } -{ -} - -ForwardDeclaredInput::~ForwardDeclaredInput() -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -ForwardDeclaredInput& ForwardDeclaredInput::operator=(const ForwardDeclaredInput& other) -{ - ForwardDeclaredInput value { other }; - - std::swap(*this, value); - - return *this; -} - -ForwardDeclaredInput& ForwardDeclaredInput::operator=(ForwardDeclaredInput&& other) noexcept -{ - nullableSelf = std::move(other.nullableSelf); - listSelves = std::move(other.listSelves); - - return *this; -} - -FirstNestedInput::FirstNestedInput() noexcept - : id {} - , second {} - , third {} -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -FirstNestedInput::FirstNestedInput( - response::IdType idArg, - SecondNestedInput secondArg, - ThirdNestedInput thirdArg) noexcept - : id { std::move(idArg) } - , second { std::move(secondArg) } - , third { std::move(thirdArg) } -{ -} - -FirstNestedInput::FirstNestedInput(const FirstNestedInput& other) - : id { service::ModifiedArgument::duplicate(other.id) } - , second { service::ModifiedArgument::duplicate(other.second) } - , third { service::ModifiedArgument::duplicate(other.third) } -{ -} - -FirstNestedInput::FirstNestedInput(FirstNestedInput&& other) noexcept - : id { std::move(other.id) } - , second { std::move(other.second) } - , third { std::move(other.third) } -{ -} - -FirstNestedInput::~FirstNestedInput() -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -FirstNestedInput& FirstNestedInput::operator=(const FirstNestedInput& other) -{ - FirstNestedInput value { other }; - - std::swap(*this, value); - - return *this; -} - -FirstNestedInput& FirstNestedInput::operator=(FirstNestedInput&& other) noexcept -{ - id = std::move(other.id); - second = std::move(other.second); - third = std::move(other.third); - - return *this; -} +namespace graphql::today { Operations::Operations(std::shared_ptr query, std::shared_ptr mutation, std::shared_ptr subscription) : service::Request({ @@ -804,11 +100,12 @@ void AddTypesToSchema(const std::shared_ptr& schema) auto typeExpensive = schema::ObjectType::Make(R"gql(Expensive)gql"sv, R"md()md"sv); schema->AddType(R"gql(Expensive)gql"sv, typeExpensive); + static const auto s_namesTaskState = getTaskStateNames(); typeTaskState->AddEnumValues({ - { service::s_namesTaskState[static_cast(today::TaskState::Unassigned)], R"md()md"sv, std::make_optional(R"md(Need to deprecate an [enum value](https://spec.graphql.org/October2021/#sec-Schema-Introspection.Deprecation))md"sv) }, - { service::s_namesTaskState[static_cast(today::TaskState::New)], R"md()md"sv, std::nullopt }, - { service::s_namesTaskState[static_cast(today::TaskState::Started)], R"md()md"sv, std::nullopt }, - { service::s_namesTaskState[static_cast(today::TaskState::Complete)], R"md()md"sv, std::nullopt } + { s_namesTaskState[static_cast(today::TaskState::Unassigned)], R"md()md"sv, std::make_optional(R"md(Need to deprecate an [enum value](https://spec.graphql.org/October2021/#sec-Schema-Introspection.Deprecation))md"sv) }, + { s_namesTaskState[static_cast(today::TaskState::New)], R"md()md"sv, std::nullopt }, + { s_namesTaskState[static_cast(today::TaskState::Started)], R"md()md"sv, std::nullopt }, + { s_namesTaskState[static_cast(today::TaskState::Complete)], R"md()md"sv, std::nullopt } }); typeCompleteTaskInput->AddInputValues({ @@ -932,5 +229,4 @@ std::shared_ptr GetSchema() return schema; } -} // namespace today -} // namespace graphql +} // namespace graphql::today diff --git a/samples/today/schema/TodaySchema.h b/samples/today/schema/TodaySchema.h index 3798db11..80b99eee 100644 --- a/samples/today/schema/TodaySchema.h +++ b/samples/today/schema/TodaySchema.h @@ -14,6 +14,8 @@ #include "graphqlservice/internal/Version.h" #include "graphqlservice/internal/Schema.h" +#include "TodaySharedTypes.h" + #include #include #include @@ -23,216 +25,7 @@ static_assert(graphql::internal::MajorVersion == 5, "regenerate with schemagen: major version mismatch"); static_assert(graphql::internal::MinorVersion == 0, "regenerate with schemagen: minor version mismatch"); -namespace graphql { -namespace today { - -enum class [[nodiscard("unnecessary conversion")]] TaskState -{ - Unassigned, - New, - Started, - Complete -}; - -[[nodiscard("unnecessary call")]] constexpr auto getTaskStateNames() noexcept -{ - using namespace std::literals; - - return std::array { - R"gql(Unassigned)gql"sv, - R"gql(New)gql"sv, - R"gql(Started)gql"sv, - R"gql(Complete)gql"sv - }; -} - -[[nodiscard("unnecessary call")]] constexpr auto getTaskStateValues() noexcept -{ - using namespace std::literals; - - return std::array, 4> { - std::make_pair(R"gql(New)gql"sv, TaskState::New), - std::make_pair(R"gql(Started)gql"sv, TaskState::Started), - std::make_pair(R"gql(Complete)gql"sv, TaskState::Complete), - std::make_pair(R"gql(Unassigned)gql"sv, TaskState::Unassigned) - }; -} - -struct [[nodiscard("unnecessary construction")]] CompleteTaskInput -{ - explicit CompleteTaskInput() noexcept; - explicit CompleteTaskInput( - response::IdType idArg, - std::optional testTaskStateArg, - std::optional isCompleteArg, - std::optional clientMutationIdArg) noexcept; - CompleteTaskInput(const CompleteTaskInput& other); - CompleteTaskInput(CompleteTaskInput&& other) noexcept; - ~CompleteTaskInput(); - - CompleteTaskInput& operator=(const CompleteTaskInput& other); - CompleteTaskInput& operator=(CompleteTaskInput&& other) noexcept; - - response::IdType id; - std::optional testTaskState; - std::optional isComplete; - std::optional clientMutationId; -}; - -struct SecondNestedInput; - -struct [[nodiscard("unnecessary construction")]] ThirdNestedInput -{ - explicit ThirdNestedInput() noexcept; - explicit ThirdNestedInput( - response::IdType idArg, - std::unique_ptr secondArg) noexcept; - ThirdNestedInput(const ThirdNestedInput& other); - ThirdNestedInput(ThirdNestedInput&& other) noexcept; - ~ThirdNestedInput(); - - ThirdNestedInput& operator=(const ThirdNestedInput& other); - ThirdNestedInput& operator=(ThirdNestedInput&& other) noexcept; - - response::IdType id; - std::unique_ptr second; -}; - -struct [[nodiscard("unnecessary construction")]] FourthNestedInput -{ - explicit FourthNestedInput() noexcept; - explicit FourthNestedInput( - response::IdType idArg) noexcept; - FourthNestedInput(const FourthNestedInput& other); - FourthNestedInput(FourthNestedInput&& other) noexcept; - ~FourthNestedInput(); - - FourthNestedInput& operator=(const FourthNestedInput& other); - FourthNestedInput& operator=(FourthNestedInput&& other) noexcept; - - response::IdType id; -}; - -struct [[nodiscard("unnecessary construction")]] IncludeNullableSelfInput -{ - explicit IncludeNullableSelfInput() noexcept; - explicit IncludeNullableSelfInput( - std::unique_ptr selfArg) noexcept; - IncludeNullableSelfInput(const IncludeNullableSelfInput& other); - IncludeNullableSelfInput(IncludeNullableSelfInput&& other) noexcept; - ~IncludeNullableSelfInput(); - - IncludeNullableSelfInput& operator=(const IncludeNullableSelfInput& other); - IncludeNullableSelfInput& operator=(IncludeNullableSelfInput&& other) noexcept; - - std::unique_ptr self; -}; - -struct [[nodiscard("unnecessary construction")]] IncludeNonNullableListSelfInput -{ - explicit IncludeNonNullableListSelfInput() noexcept; - explicit IncludeNonNullableListSelfInput( - std::vector selvesArg) noexcept; - IncludeNonNullableListSelfInput(const IncludeNonNullableListSelfInput& other); - IncludeNonNullableListSelfInput(IncludeNonNullableListSelfInput&& other) noexcept; - ~IncludeNonNullableListSelfInput(); - - IncludeNonNullableListSelfInput& operator=(const IncludeNonNullableListSelfInput& other); - IncludeNonNullableListSelfInput& operator=(IncludeNonNullableListSelfInput&& other) noexcept; - - std::vector selves; -}; - -struct [[nodiscard("unnecessary construction")]] StringOperationFilterInput -{ - explicit StringOperationFilterInput() noexcept; - explicit StringOperationFilterInput( - std::optional> and_Arg, - std::optional> or_Arg, - std::optional equalArg, - std::optional notEqualArg, - std::optional containsArg, - std::optional notContainsArg, - std::optional> inArg, - std::optional> notInArg, - std::optional startsWithArg, - std::optional notStartsWithArg, - std::optional endsWithArg, - std::optional notEndsWithArg) noexcept; - StringOperationFilterInput(const StringOperationFilterInput& other); - StringOperationFilterInput(StringOperationFilterInput&& other) noexcept; - ~StringOperationFilterInput(); - - StringOperationFilterInput& operator=(const StringOperationFilterInput& other); - StringOperationFilterInput& operator=(StringOperationFilterInput&& other) noexcept; - - std::optional> and_; - std::optional> or_; - std::optional equal; - std::optional notEqual; - std::optional contains; - std::optional notContains; - std::optional> in; - std::optional> notIn; - std::optional startsWith; - std::optional notStartsWith; - std::optional endsWith; - std::optional notEndsWith; -}; - -struct [[nodiscard("unnecessary construction")]] SecondNestedInput -{ - explicit SecondNestedInput() noexcept; - explicit SecondNestedInput( - response::IdType idArg, - ThirdNestedInput thirdArg) noexcept; - SecondNestedInput(const SecondNestedInput& other); - SecondNestedInput(SecondNestedInput&& other) noexcept; - ~SecondNestedInput(); - - SecondNestedInput& operator=(const SecondNestedInput& other); - SecondNestedInput& operator=(SecondNestedInput&& other) noexcept; - - response::IdType id; - ThirdNestedInput third; -}; - -struct [[nodiscard("unnecessary construction")]] ForwardDeclaredInput -{ - explicit ForwardDeclaredInput() noexcept; - explicit ForwardDeclaredInput( - std::unique_ptr nullableSelfArg, - IncludeNonNullableListSelfInput listSelvesArg) noexcept; - ForwardDeclaredInput(const ForwardDeclaredInput& other); - ForwardDeclaredInput(ForwardDeclaredInput&& other) noexcept; - ~ForwardDeclaredInput(); - - ForwardDeclaredInput& operator=(const ForwardDeclaredInput& other); - ForwardDeclaredInput& operator=(ForwardDeclaredInput&& other) noexcept; - - std::unique_ptr nullableSelf; - IncludeNonNullableListSelfInput listSelves; -}; - -struct [[nodiscard("unnecessary construction")]] FirstNestedInput -{ - explicit FirstNestedInput() noexcept; - explicit FirstNestedInput( - response::IdType idArg, - SecondNestedInput secondArg, - ThirdNestedInput thirdArg) noexcept; - FirstNestedInput(const FirstNestedInput& other); - FirstNestedInput(FirstNestedInput&& other) noexcept; - ~FirstNestedInput(); - - FirstNestedInput& operator=(const FirstNestedInput& other); - FirstNestedInput& operator=(FirstNestedInput&& other) noexcept; - - response::IdType id; - SecondNestedInput second; - ThirdNestedInput third; -}; - +namespace graphql::today { namespace object { class Node; @@ -303,7 +96,6 @@ void AddExpensiveDetails(const std::shared_ptr& typeExpensiv std::shared_ptr GetSchema(); -} // namespace today -} // namespace graphql +} // namespace graphql::today #endif // TODAYSCHEMA_H diff --git a/samples/today/schema/TodaySchema.ixx b/samples/today/schema/TodaySchema.ixx index 7bfef47c..56aad8e6 100644 --- a/samples/today/schema/TodaySchema.ixx +++ b/samples/today/schema/TodaySchema.ixx @@ -9,6 +9,8 @@ module; export module GraphQL.Today.TodaySchema; +export import GraphQL.Today.TodaySharedTypes; + export import GraphQL.Today.NodeObject; export import GraphQL.Today.UnionTypeObject; export import GraphQL.Today.QueryObject; @@ -30,20 +32,6 @@ export import GraphQL.Today.ExpensiveObject; export namespace graphql::today { -using today::TaskState; -using today::getTaskStateNames; -using today::getTaskStateValues; - -using today::CompleteTaskInput; -using today::ThirdNestedInput; -using today::FourthNestedInput; -using today::IncludeNullableSelfInput; -using today::IncludeNonNullableListSelfInput; -using today::StringOperationFilterInput; -using today::SecondNestedInput; -using today::ForwardDeclaredInput; -using today::FirstNestedInput; - using today::Operations; using today::AddNodeDetails; diff --git a/samples/today/schema/TodaySharedTypes.cpp b/samples/today/schema/TodaySharedTypes.cpp new file mode 100644 index 00000000..d3a0c4a0 --- /dev/null +++ b/samples/today/schema/TodaySharedTypes.cpp @@ -0,0 +1,736 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// WARNING! Do not edit this file manually, your changes will be overwritten. + +#include "graphqlservice/GraphQLService.h" + +#include "TodaySharedTypes.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std::literals; + +namespace graphql { +namespace service { + +static const auto s_namesTaskState = today::getTaskStateNames(); +static const auto s_valuesTaskState = today::getTaskStateValues(); + +template <> +today::TaskState Argument::convert(const response::Value& value) +{ + if (!value.maybe_enum()) + { + throw service::schema_exception { { R"ex(not a valid TaskState value)ex" } }; + } + + const auto result = internal::sorted_map_lookup( + s_valuesTaskState, + std::string_view { value.get() }); + + if (!result) + { + throw service::schema_exception { { R"ex(not a valid TaskState value)ex" } }; + } + + return *result; +} + +template <> +service::AwaitableResolver Result::convert(service::AwaitableScalar result, ResolverParams&& params) +{ + return ModifiedResult::resolve(std::move(result), std::move(params), + [](today::TaskState value, const ResolverParams&) + { + response::Value resolvedResult(response::Type::EnumValue); + + resolvedResult.set(std::string { s_namesTaskState[static_cast(value)] }); + + return resolvedResult; + }); +} + +template <> +void Result::validateScalar(const response::Value& value) +{ + if (!value.maybe_enum()) + { + throw service::schema_exception { { R"ex(not a valid TaskState value)ex" } }; + } + + const auto [itr, itrEnd] = internal::sorted_map_equal_range( + s_valuesTaskState.begin(), + s_valuesTaskState.end(), + std::string_view { value.get() }); + + if (itr == itrEnd) + { + throw service::schema_exception { { R"ex(not a valid TaskState value)ex" } }; + } +} + +template <> +today::CompleteTaskInput Argument::convert(const response::Value& value) +{ + const auto defaultValue = []() + { + response::Value values(response::Type::Map); + response::Value entry; + + entry = response::Value(true); + values.emplace_back("isComplete", std::move(entry)); + + return values; + }(); + + auto valueId = service::ModifiedArgument::require("id", value); + auto valueTestTaskState = service::ModifiedArgument::require("testTaskState", value); + auto pairIsComplete = service::ModifiedArgument::find("isComplete", value); + auto valueIsComplete = (pairIsComplete.second + ? std::move(pairIsComplete.first) + : service::ModifiedArgument::require("isComplete", defaultValue)); + auto valueClientMutationId = service::ModifiedArgument::require("clientMutationId", value); + + return today::CompleteTaskInput { + std::move(valueId), + valueTestTaskState, + std::move(valueIsComplete), + std::move(valueClientMutationId) + }; +} + +template <> +today::ThirdNestedInput Argument::convert(const response::Value& value) +{ + auto valueId = service::ModifiedArgument::require("id", value); + auto valueSecond = service::ModifiedArgument::require("second", value); + + return today::ThirdNestedInput { + std::move(valueId), + std::move(valueSecond) + }; +} + +template <> +today::FourthNestedInput Argument::convert(const response::Value& value) +{ + auto valueId = service::ModifiedArgument::require("id", value); + + return today::FourthNestedInput { + std::move(valueId) + }; +} + +template <> +today::IncludeNullableSelfInput Argument::convert(const response::Value& value) +{ + auto valueSelf = service::ModifiedArgument::require("self", value); + + return today::IncludeNullableSelfInput { + std::move(valueSelf) + }; +} + +template <> +today::IncludeNonNullableListSelfInput Argument::convert(const response::Value& value) +{ + auto valueSelves = service::ModifiedArgument::require("selves", value); + + return today::IncludeNonNullableListSelfInput { + std::move(valueSelves) + }; +} + +template <> +today::StringOperationFilterInput Argument::convert(const response::Value& value) +{ + auto valueAnd_ = service::ModifiedArgument::require("and", value); + auto valueOr_ = service::ModifiedArgument::require("or", value); + auto valueEqual = service::ModifiedArgument::require("equal", value); + auto valueNotEqual = service::ModifiedArgument::require("notEqual", value); + auto valueContains = service::ModifiedArgument::require("contains", value); + auto valueNotContains = service::ModifiedArgument::require("notContains", value); + auto valueIn = service::ModifiedArgument::require("in", value); + auto valueNotIn = service::ModifiedArgument::require("notIn", value); + auto valueStartsWith = service::ModifiedArgument::require("startsWith", value); + auto valueNotStartsWith = service::ModifiedArgument::require("notStartsWith", value); + auto valueEndsWith = service::ModifiedArgument::require("endsWith", value); + auto valueNotEndsWith = service::ModifiedArgument::require("notEndsWith", value); + + return today::StringOperationFilterInput { + std::move(valueAnd_), + std::move(valueOr_), + std::move(valueEqual), + std::move(valueNotEqual), + std::move(valueContains), + std::move(valueNotContains), + std::move(valueIn), + std::move(valueNotIn), + std::move(valueStartsWith), + std::move(valueNotStartsWith), + std::move(valueEndsWith), + std::move(valueNotEndsWith) + }; +} + +template <> +today::SecondNestedInput Argument::convert(const response::Value& value) +{ + auto valueId = service::ModifiedArgument::require("id", value); + auto valueThird = service::ModifiedArgument::require("third", value); + + return today::SecondNestedInput { + std::move(valueId), + std::move(valueThird) + }; +} + +template <> +today::ForwardDeclaredInput Argument::convert(const response::Value& value) +{ + auto valueNullableSelf = service::ModifiedArgument::require("nullableSelf", value); + auto valueListSelves = service::ModifiedArgument::require("listSelves", value); + + return today::ForwardDeclaredInput { + std::move(valueNullableSelf), + std::move(valueListSelves) + }; +} + +template <> +today::FirstNestedInput Argument::convert(const response::Value& value) +{ + auto valueId = service::ModifiedArgument::require("id", value); + auto valueSecond = service::ModifiedArgument::require("second", value); + auto valueThird = service::ModifiedArgument::require("third", value); + + return today::FirstNestedInput { + std::move(valueId), + std::move(valueSecond), + std::move(valueThird) + }; +} + +} // namespace service + +namespace today { + +CompleteTaskInput::CompleteTaskInput() noexcept + : id {} + , testTaskState {} + , isComplete {} + , clientMutationId {} +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +CompleteTaskInput::CompleteTaskInput( + response::IdType idArg, + std::optional testTaskStateArg, + std::optional isCompleteArg, + std::optional clientMutationIdArg) noexcept + : id { std::move(idArg) } + , testTaskState { std::move(testTaskStateArg) } + , isComplete { std::move(isCompleteArg) } + , clientMutationId { std::move(clientMutationIdArg) } +{ +} + +CompleteTaskInput::CompleteTaskInput(const CompleteTaskInput& other) + : id { service::ModifiedArgument::duplicate(other.id) } + , testTaskState { service::ModifiedArgument::duplicate(other.testTaskState) } + , isComplete { service::ModifiedArgument::duplicate(other.isComplete) } + , clientMutationId { service::ModifiedArgument::duplicate(other.clientMutationId) } +{ +} + +CompleteTaskInput::CompleteTaskInput(CompleteTaskInput&& other) noexcept + : id { std::move(other.id) } + , testTaskState { std::move(other.testTaskState) } + , isComplete { std::move(other.isComplete) } + , clientMutationId { std::move(other.clientMutationId) } +{ +} + +CompleteTaskInput::~CompleteTaskInput() +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +CompleteTaskInput& CompleteTaskInput::operator=(const CompleteTaskInput& other) +{ + CompleteTaskInput value { other }; + + std::swap(*this, value); + + return *this; +} + +CompleteTaskInput& CompleteTaskInput::operator=(CompleteTaskInput&& other) noexcept +{ + id = std::move(other.id); + testTaskState = std::move(other.testTaskState); + isComplete = std::move(other.isComplete); + clientMutationId = std::move(other.clientMutationId); + + return *this; +} + + +ThirdNestedInput::ThirdNestedInput() noexcept + : id {} + , second {} +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +ThirdNestedInput::ThirdNestedInput( + response::IdType idArg, + std::unique_ptr secondArg) noexcept + : id { std::move(idArg) } + , second { std::move(secondArg) } +{ +} + +ThirdNestedInput::ThirdNestedInput(const ThirdNestedInput& other) + : id { service::ModifiedArgument::duplicate(other.id) } + , second { service::ModifiedArgument::duplicate(other.second) } +{ +} + +ThirdNestedInput::ThirdNestedInput(ThirdNestedInput&& other) noexcept + : id { std::move(other.id) } + , second { std::move(other.second) } +{ +} + +ThirdNestedInput::~ThirdNestedInput() +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +ThirdNestedInput& ThirdNestedInput::operator=(const ThirdNestedInput& other) +{ + ThirdNestedInput value { other }; + + std::swap(*this, value); + + return *this; +} + +ThirdNestedInput& ThirdNestedInput::operator=(ThirdNestedInput&& other) noexcept +{ + id = std::move(other.id); + second = std::move(other.second); + + return *this; +} + + +FourthNestedInput::FourthNestedInput() noexcept + : id {} +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +FourthNestedInput::FourthNestedInput( + response::IdType idArg) noexcept + : id { std::move(idArg) } +{ +} + +FourthNestedInput::FourthNestedInput(const FourthNestedInput& other) + : id { service::ModifiedArgument::duplicate(other.id) } +{ +} + +FourthNestedInput::FourthNestedInput(FourthNestedInput&& other) noexcept + : id { std::move(other.id) } +{ +} + +FourthNestedInput::~FourthNestedInput() +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +FourthNestedInput& FourthNestedInput::operator=(const FourthNestedInput& other) +{ + FourthNestedInput value { other }; + + std::swap(*this, value); + + return *this; +} + +FourthNestedInput& FourthNestedInput::operator=(FourthNestedInput&& other) noexcept +{ + id = std::move(other.id); + + return *this; +} + + +IncludeNullableSelfInput::IncludeNullableSelfInput() noexcept + : self {} +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +IncludeNullableSelfInput::IncludeNullableSelfInput( + std::unique_ptr selfArg) noexcept + : self { std::move(selfArg) } +{ +} + +IncludeNullableSelfInput::IncludeNullableSelfInput(const IncludeNullableSelfInput& other) + : self { service::ModifiedArgument::duplicate(other.self) } +{ +} + +IncludeNullableSelfInput::IncludeNullableSelfInput(IncludeNullableSelfInput&& other) noexcept + : self { std::move(other.self) } +{ +} + +IncludeNullableSelfInput::~IncludeNullableSelfInput() +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +IncludeNullableSelfInput& IncludeNullableSelfInput::operator=(const IncludeNullableSelfInput& other) +{ + IncludeNullableSelfInput value { other }; + + std::swap(*this, value); + + return *this; +} + +IncludeNullableSelfInput& IncludeNullableSelfInput::operator=(IncludeNullableSelfInput&& other) noexcept +{ + self = std::move(other.self); + + return *this; +} + + +IncludeNonNullableListSelfInput::IncludeNonNullableListSelfInput() noexcept + : selves {} +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +IncludeNonNullableListSelfInput::IncludeNonNullableListSelfInput( + std::vector selvesArg) noexcept + : selves { std::move(selvesArg) } +{ +} + +IncludeNonNullableListSelfInput::IncludeNonNullableListSelfInput(const IncludeNonNullableListSelfInput& other) + : selves { service::ModifiedArgument::duplicate(other.selves) } +{ +} + +IncludeNonNullableListSelfInput::IncludeNonNullableListSelfInput(IncludeNonNullableListSelfInput&& other) noexcept + : selves { std::move(other.selves) } +{ +} + +IncludeNonNullableListSelfInput::~IncludeNonNullableListSelfInput() +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +IncludeNonNullableListSelfInput& IncludeNonNullableListSelfInput::operator=(const IncludeNonNullableListSelfInput& other) +{ + IncludeNonNullableListSelfInput value { other }; + + std::swap(*this, value); + + return *this; +} + +IncludeNonNullableListSelfInput& IncludeNonNullableListSelfInput::operator=(IncludeNonNullableListSelfInput&& other) noexcept +{ + selves = std::move(other.selves); + + return *this; +} + + +StringOperationFilterInput::StringOperationFilterInput() noexcept + : and_ {} + , or_ {} + , equal {} + , notEqual {} + , contains {} + , notContains {} + , in {} + , notIn {} + , startsWith {} + , notStartsWith {} + , endsWith {} + , notEndsWith {} +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +StringOperationFilterInput::StringOperationFilterInput( + std::optional> and_Arg, + std::optional> or_Arg, + std::optional equalArg, + std::optional notEqualArg, + std::optional containsArg, + std::optional notContainsArg, + std::optional> inArg, + std::optional> notInArg, + std::optional startsWithArg, + std::optional notStartsWithArg, + std::optional endsWithArg, + std::optional notEndsWithArg) noexcept + : and_ { std::move(and_Arg) } + , or_ { std::move(or_Arg) } + , equal { std::move(equalArg) } + , notEqual { std::move(notEqualArg) } + , contains { std::move(containsArg) } + , notContains { std::move(notContainsArg) } + , in { std::move(inArg) } + , notIn { std::move(notInArg) } + , startsWith { std::move(startsWithArg) } + , notStartsWith { std::move(notStartsWithArg) } + , endsWith { std::move(endsWithArg) } + , notEndsWith { std::move(notEndsWithArg) } +{ +} + +StringOperationFilterInput::StringOperationFilterInput(const StringOperationFilterInput& other) + : and_ { service::ModifiedArgument::duplicate(other.and_) } + , or_ { service::ModifiedArgument::duplicate(other.or_) } + , equal { service::ModifiedArgument::duplicate(other.equal) } + , notEqual { service::ModifiedArgument::duplicate(other.notEqual) } + , contains { service::ModifiedArgument::duplicate(other.contains) } + , notContains { service::ModifiedArgument::duplicate(other.notContains) } + , in { service::ModifiedArgument::duplicate(other.in) } + , notIn { service::ModifiedArgument::duplicate(other.notIn) } + , startsWith { service::ModifiedArgument::duplicate(other.startsWith) } + , notStartsWith { service::ModifiedArgument::duplicate(other.notStartsWith) } + , endsWith { service::ModifiedArgument::duplicate(other.endsWith) } + , notEndsWith { service::ModifiedArgument::duplicate(other.notEndsWith) } +{ +} + +StringOperationFilterInput::StringOperationFilterInput(StringOperationFilterInput&& other) noexcept + : and_ { std::move(other.and_) } + , or_ { std::move(other.or_) } + , equal { std::move(other.equal) } + , notEqual { std::move(other.notEqual) } + , contains { std::move(other.contains) } + , notContains { std::move(other.notContains) } + , in { std::move(other.in) } + , notIn { std::move(other.notIn) } + , startsWith { std::move(other.startsWith) } + , notStartsWith { std::move(other.notStartsWith) } + , endsWith { std::move(other.endsWith) } + , notEndsWith { std::move(other.notEndsWith) } +{ +} + +StringOperationFilterInput::~StringOperationFilterInput() +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +StringOperationFilterInput& StringOperationFilterInput::operator=(const StringOperationFilterInput& other) +{ + StringOperationFilterInput value { other }; + + std::swap(*this, value); + + return *this; +} + +StringOperationFilterInput& StringOperationFilterInput::operator=(StringOperationFilterInput&& other) noexcept +{ + and_ = std::move(other.and_); + or_ = std::move(other.or_); + equal = std::move(other.equal); + notEqual = std::move(other.notEqual); + contains = std::move(other.contains); + notContains = std::move(other.notContains); + in = std::move(other.in); + notIn = std::move(other.notIn); + startsWith = std::move(other.startsWith); + notStartsWith = std::move(other.notStartsWith); + endsWith = std::move(other.endsWith); + notEndsWith = std::move(other.notEndsWith); + + return *this; +} + + +SecondNestedInput::SecondNestedInput() noexcept + : id {} + , third {} +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +SecondNestedInput::SecondNestedInput( + response::IdType idArg, + ThirdNestedInput thirdArg) noexcept + : id { std::move(idArg) } + , third { std::move(thirdArg) } +{ +} + +SecondNestedInput::SecondNestedInput(const SecondNestedInput& other) + : id { service::ModifiedArgument::duplicate(other.id) } + , third { service::ModifiedArgument::duplicate(other.third) } +{ +} + +SecondNestedInput::SecondNestedInput(SecondNestedInput&& other) noexcept + : id { std::move(other.id) } + , third { std::move(other.third) } +{ +} + +SecondNestedInput::~SecondNestedInput() +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +SecondNestedInput& SecondNestedInput::operator=(const SecondNestedInput& other) +{ + SecondNestedInput value { other }; + + std::swap(*this, value); + + return *this; +} + +SecondNestedInput& SecondNestedInput::operator=(SecondNestedInput&& other) noexcept +{ + id = std::move(other.id); + third = std::move(other.third); + + return *this; +} + + +ForwardDeclaredInput::ForwardDeclaredInput() noexcept + : nullableSelf {} + , listSelves {} +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +ForwardDeclaredInput::ForwardDeclaredInput( + std::unique_ptr nullableSelfArg, + IncludeNonNullableListSelfInput listSelvesArg) noexcept + : nullableSelf { std::move(nullableSelfArg) } + , listSelves { std::move(listSelvesArg) } +{ +} + +ForwardDeclaredInput::ForwardDeclaredInput(const ForwardDeclaredInput& other) + : nullableSelf { service::ModifiedArgument::duplicate(other.nullableSelf) } + , listSelves { service::ModifiedArgument::duplicate(other.listSelves) } +{ +} + +ForwardDeclaredInput::ForwardDeclaredInput(ForwardDeclaredInput&& other) noexcept + : nullableSelf { std::move(other.nullableSelf) } + , listSelves { std::move(other.listSelves) } +{ +} + +ForwardDeclaredInput::~ForwardDeclaredInput() +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +ForwardDeclaredInput& ForwardDeclaredInput::operator=(const ForwardDeclaredInput& other) +{ + ForwardDeclaredInput value { other }; + + std::swap(*this, value); + + return *this; +} + +ForwardDeclaredInput& ForwardDeclaredInput::operator=(ForwardDeclaredInput&& other) noexcept +{ + nullableSelf = std::move(other.nullableSelf); + listSelves = std::move(other.listSelves); + + return *this; +} + + +FirstNestedInput::FirstNestedInput() noexcept + : id {} + , second {} + , third {} +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +FirstNestedInput::FirstNestedInput( + response::IdType idArg, + SecondNestedInput secondArg, + ThirdNestedInput thirdArg) noexcept + : id { std::move(idArg) } + , second { std::move(secondArg) } + , third { std::move(thirdArg) } +{ +} + +FirstNestedInput::FirstNestedInput(const FirstNestedInput& other) + : id { service::ModifiedArgument::duplicate(other.id) } + , second { service::ModifiedArgument::duplicate(other.second) } + , third { service::ModifiedArgument::duplicate(other.third) } +{ +} + +FirstNestedInput::FirstNestedInput(FirstNestedInput&& other) noexcept + : id { std::move(other.id) } + , second { std::move(other.second) } + , third { std::move(other.third) } +{ +} + +FirstNestedInput::~FirstNestedInput() +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +FirstNestedInput& FirstNestedInput::operator=(const FirstNestedInput& other) +{ + FirstNestedInput value { other }; + + std::swap(*this, value); + + return *this; +} + +FirstNestedInput& FirstNestedInput::operator=(FirstNestedInput&& other) noexcept +{ + id = std::move(other.id); + second = std::move(other.second); + third = std::move(other.third); + + return *this; +} + +} // namespace today +} // namespace graphql diff --git a/samples/today/schema/TodaySharedTypes.h b/samples/today/schema/TodaySharedTypes.h new file mode 100644 index 00000000..b3c7b086 --- /dev/null +++ b/samples/today/schema/TodaySharedTypes.h @@ -0,0 +1,239 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// WARNING! Do not edit this file manually, your changes will be overwritten. + +#pragma once + +#ifndef TODAYSHAREDTYPES_H +#define TODAYSHAREDTYPES_H + +#include "graphqlservice/GraphQLResponse.h" + +#include "graphqlservice/internal/Version.h" + +#include +#include +#include +#include +#include +#include + +// Check if the library version is compatible with schemagen 5.0.0 +static_assert(graphql::internal::MajorVersion == 5, "regenerate with schemagen: major version mismatch"); +static_assert(graphql::internal::MinorVersion == 0, "regenerate with schemagen: minor version mismatch"); + +namespace graphql { +namespace today { + +enum class [[nodiscard("unnecessary conversion")]] TaskState +{ + Unassigned, + New, + Started, + Complete +}; + +[[nodiscard("unnecessary call")]] constexpr auto getTaskStateNames() noexcept +{ + using namespace std::literals; + + return std::array { + R"gql(Unassigned)gql"sv, + R"gql(New)gql"sv, + R"gql(Started)gql"sv, + R"gql(Complete)gql"sv + }; +} + +[[nodiscard("unnecessary call")]] constexpr auto getTaskStateValues() noexcept +{ + using namespace std::literals; + + return std::array, 4> { + std::make_pair(R"gql(New)gql"sv, TaskState::New), + std::make_pair(R"gql(Started)gql"sv, TaskState::Started), + std::make_pair(R"gql(Complete)gql"sv, TaskState::Complete), + std::make_pair(R"gql(Unassigned)gql"sv, TaskState::Unassigned) + }; +} + +struct [[nodiscard("unnecessary construction")]] CompleteTaskInput +{ + explicit CompleteTaskInput() noexcept; + explicit CompleteTaskInput( + response::IdType idArg, + std::optional testTaskStateArg, + std::optional isCompleteArg, + std::optional clientMutationIdArg) noexcept; + CompleteTaskInput(const CompleteTaskInput& other); + CompleteTaskInput(CompleteTaskInput&& other) noexcept; + ~CompleteTaskInput(); + + CompleteTaskInput& operator=(const CompleteTaskInput& other); + CompleteTaskInput& operator=(CompleteTaskInput&& other) noexcept; + + response::IdType id; + std::optional testTaskState; + std::optional isComplete; + std::optional clientMutationId; +}; + +struct SecondNestedInput; + +struct [[nodiscard("unnecessary construction")]] ThirdNestedInput +{ + explicit ThirdNestedInput() noexcept; + explicit ThirdNestedInput( + response::IdType idArg, + std::unique_ptr secondArg) noexcept; + ThirdNestedInput(const ThirdNestedInput& other); + ThirdNestedInput(ThirdNestedInput&& other) noexcept; + ~ThirdNestedInput(); + + ThirdNestedInput& operator=(const ThirdNestedInput& other); + ThirdNestedInput& operator=(ThirdNestedInput&& other) noexcept; + + response::IdType id; + std::unique_ptr second; +}; + +struct [[nodiscard("unnecessary construction")]] FourthNestedInput +{ + explicit FourthNestedInput() noexcept; + explicit FourthNestedInput( + response::IdType idArg) noexcept; + FourthNestedInput(const FourthNestedInput& other); + FourthNestedInput(FourthNestedInput&& other) noexcept; + ~FourthNestedInput(); + + FourthNestedInput& operator=(const FourthNestedInput& other); + FourthNestedInput& operator=(FourthNestedInput&& other) noexcept; + + response::IdType id; +}; + +struct [[nodiscard("unnecessary construction")]] IncludeNullableSelfInput +{ + explicit IncludeNullableSelfInput() noexcept; + explicit IncludeNullableSelfInput( + std::unique_ptr selfArg) noexcept; + IncludeNullableSelfInput(const IncludeNullableSelfInput& other); + IncludeNullableSelfInput(IncludeNullableSelfInput&& other) noexcept; + ~IncludeNullableSelfInput(); + + IncludeNullableSelfInput& operator=(const IncludeNullableSelfInput& other); + IncludeNullableSelfInput& operator=(IncludeNullableSelfInput&& other) noexcept; + + std::unique_ptr self; +}; + +struct [[nodiscard("unnecessary construction")]] IncludeNonNullableListSelfInput +{ + explicit IncludeNonNullableListSelfInput() noexcept; + explicit IncludeNonNullableListSelfInput( + std::vector selvesArg) noexcept; + IncludeNonNullableListSelfInput(const IncludeNonNullableListSelfInput& other); + IncludeNonNullableListSelfInput(IncludeNonNullableListSelfInput&& other) noexcept; + ~IncludeNonNullableListSelfInput(); + + IncludeNonNullableListSelfInput& operator=(const IncludeNonNullableListSelfInput& other); + IncludeNonNullableListSelfInput& operator=(IncludeNonNullableListSelfInput&& other) noexcept; + + std::vector selves; +}; + +struct [[nodiscard("unnecessary construction")]] StringOperationFilterInput +{ + explicit StringOperationFilterInput() noexcept; + explicit StringOperationFilterInput( + std::optional> and_Arg, + std::optional> or_Arg, + std::optional equalArg, + std::optional notEqualArg, + std::optional containsArg, + std::optional notContainsArg, + std::optional> inArg, + std::optional> notInArg, + std::optional startsWithArg, + std::optional notStartsWithArg, + std::optional endsWithArg, + std::optional notEndsWithArg) noexcept; + StringOperationFilterInput(const StringOperationFilterInput& other); + StringOperationFilterInput(StringOperationFilterInput&& other) noexcept; + ~StringOperationFilterInput(); + + StringOperationFilterInput& operator=(const StringOperationFilterInput& other); + StringOperationFilterInput& operator=(StringOperationFilterInput&& other) noexcept; + + std::optional> and_; + std::optional> or_; + std::optional equal; + std::optional notEqual; + std::optional contains; + std::optional notContains; + std::optional> in; + std::optional> notIn; + std::optional startsWith; + std::optional notStartsWith; + std::optional endsWith; + std::optional notEndsWith; +}; + +struct [[nodiscard("unnecessary construction")]] SecondNestedInput +{ + explicit SecondNestedInput() noexcept; + explicit SecondNestedInput( + response::IdType idArg, + ThirdNestedInput thirdArg) noexcept; + SecondNestedInput(const SecondNestedInput& other); + SecondNestedInput(SecondNestedInput&& other) noexcept; + ~SecondNestedInput(); + + SecondNestedInput& operator=(const SecondNestedInput& other); + SecondNestedInput& operator=(SecondNestedInput&& other) noexcept; + + response::IdType id; + ThirdNestedInput third; +}; + +struct [[nodiscard("unnecessary construction")]] ForwardDeclaredInput +{ + explicit ForwardDeclaredInput() noexcept; + explicit ForwardDeclaredInput( + std::unique_ptr nullableSelfArg, + IncludeNonNullableListSelfInput listSelvesArg) noexcept; + ForwardDeclaredInput(const ForwardDeclaredInput& other); + ForwardDeclaredInput(ForwardDeclaredInput&& other) noexcept; + ~ForwardDeclaredInput(); + + ForwardDeclaredInput& operator=(const ForwardDeclaredInput& other); + ForwardDeclaredInput& operator=(ForwardDeclaredInput&& other) noexcept; + + std::unique_ptr nullableSelf; + IncludeNonNullableListSelfInput listSelves; +}; + +struct [[nodiscard("unnecessary construction")]] FirstNestedInput +{ + explicit FirstNestedInput() noexcept; + explicit FirstNestedInput( + response::IdType idArg, + SecondNestedInput secondArg, + ThirdNestedInput thirdArg) noexcept; + FirstNestedInput(const FirstNestedInput& other); + FirstNestedInput(FirstNestedInput&& other) noexcept; + ~FirstNestedInput(); + + FirstNestedInput& operator=(const FirstNestedInput& other); + FirstNestedInput& operator=(FirstNestedInput&& other) noexcept; + + response::IdType id; + SecondNestedInput second; + ThirdNestedInput third; +}; + +} // namespace today +} // namespace graphql + +#endif // TODAYSHAREDTYPES_H diff --git a/samples/today/schema/TodaySharedTypes.ixx b/samples/today/schema/TodaySharedTypes.ixx new file mode 100644 index 00000000..ee76a95a --- /dev/null +++ b/samples/today/schema/TodaySharedTypes.ixx @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// WARNING! Do not edit this file manually, your changes will be overwritten. + +module; + +#include "TodaySharedTypes.h" + +export module GraphQL.Today.TodaySharedTypes; + +export namespace graphql::today { + +using today::TaskState; +using today::getTaskStateNames; +using today::getTaskStateValues; + +using today::CompleteTaskInput; +using today::ThirdNestedInput; +using today::FourthNestedInput; +using today::IncludeNullableSelfInput; +using today::IncludeNonNullableListSelfInput; +using today::StringOperationFilterInput; +using today::SecondNestedInput; +using today::ForwardDeclaredInput; +using today::FirstNestedInput; + +} // namespace graphql::today diff --git a/samples/today/schema/today_schema_files b/samples/today/schema/today_schema_files index a9ed9ecf..2e24cdcf 100644 --- a/samples/today/schema/today_schema_files +++ b/samples/today/schema/today_schema_files @@ -1,3 +1,4 @@ +TodaySharedTypes.cpp TodaySchema.cpp NodeObject.cpp UnionTypeObject.cpp diff --git a/samples/validation/schema/ValidationSchema.cpp b/samples/validation/schema/ValidationSchema.cpp index bc7c42b8..4a99aec5 100644 --- a/samples/validation/schema/ValidationSchema.cpp +++ b/samples/validation/schema/ValidationSchema.cpp @@ -22,185 +22,7 @@ using namespace std::literals; -namespace graphql { -namespace service { - -static const auto s_namesDogCommand = validation::getDogCommandNames(); -static const auto s_valuesDogCommand = validation::getDogCommandValues(); - -template <> -validation::DogCommand Argument::convert(const response::Value& value) -{ - if (!value.maybe_enum()) - { - throw service::schema_exception { { R"ex(not a valid DogCommand value)ex" } }; - } - - const auto result = internal::sorted_map_lookup( - s_valuesDogCommand, - std::string_view { value.get() }); - - if (!result) - { - throw service::schema_exception { { R"ex(not a valid DogCommand value)ex" } }; - } - - return *result; -} - -template <> -service::AwaitableResolver Result::convert(service::AwaitableScalar result, ResolverParams&& params) -{ - return ModifiedResult::resolve(std::move(result), std::move(params), - [](validation::DogCommand value, const ResolverParams&) - { - response::Value resolvedResult(response::Type::EnumValue); - - resolvedResult.set(std::string { s_namesDogCommand[static_cast(value)] }); - - return resolvedResult; - }); -} - -template <> -void Result::validateScalar(const response::Value& value) -{ - if (!value.maybe_enum()) - { - throw service::schema_exception { { R"ex(not a valid DogCommand value)ex" } }; - } - - const auto [itr, itrEnd] = internal::sorted_map_equal_range( - s_valuesDogCommand.begin(), - s_valuesDogCommand.end(), - std::string_view { value.get() }); - - if (itr == itrEnd) - { - throw service::schema_exception { { R"ex(not a valid DogCommand value)ex" } }; - } -} - -static const auto s_namesCatCommand = validation::getCatCommandNames(); -static const auto s_valuesCatCommand = validation::getCatCommandValues(); - -template <> -validation::CatCommand Argument::convert(const response::Value& value) -{ - if (!value.maybe_enum()) - { - throw service::schema_exception { { R"ex(not a valid CatCommand value)ex" } }; - } - - const auto result = internal::sorted_map_lookup( - s_valuesCatCommand, - std::string_view { value.get() }); - - if (!result) - { - throw service::schema_exception { { R"ex(not a valid CatCommand value)ex" } }; - } - - return *result; -} - -template <> -service::AwaitableResolver Result::convert(service::AwaitableScalar result, ResolverParams&& params) -{ - return ModifiedResult::resolve(std::move(result), std::move(params), - [](validation::CatCommand value, const ResolverParams&) - { - response::Value resolvedResult(response::Type::EnumValue); - - resolvedResult.set(std::string { s_namesCatCommand[static_cast(value)] }); - - return resolvedResult; - }); -} - -template <> -void Result::validateScalar(const response::Value& value) -{ - if (!value.maybe_enum()) - { - throw service::schema_exception { { R"ex(not a valid CatCommand value)ex" } }; - } - - const auto [itr, itrEnd] = internal::sorted_map_equal_range( - s_valuesCatCommand.begin(), - s_valuesCatCommand.end(), - std::string_view { value.get() }); - - if (itr == itrEnd) - { - throw service::schema_exception { { R"ex(not a valid CatCommand value)ex" } }; - } -} - -template <> -validation::ComplexInput Argument::convert(const response::Value& value) -{ - auto valueName = service::ModifiedArgument::require("name", value); - auto valueOwner = service::ModifiedArgument::require("owner", value); - - return validation::ComplexInput { - std::move(valueName), - std::move(valueOwner) - }; -} - -} // namespace service - -namespace validation { - -ComplexInput::ComplexInput() noexcept - : name {} - , owner {} -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -ComplexInput::ComplexInput( - std::optional nameArg, - std::optional ownerArg) noexcept - : name { std::move(nameArg) } - , owner { std::move(ownerArg) } -{ -} - -ComplexInput::ComplexInput(const ComplexInput& other) - : name { service::ModifiedArgument::duplicate(other.name) } - , owner { service::ModifiedArgument::duplicate(other.owner) } -{ -} - -ComplexInput::ComplexInput(ComplexInput&& other) noexcept - : name { std::move(other.name) } - , owner { std::move(other.owner) } -{ -} - -ComplexInput::~ComplexInput() -{ - // Explicit definition to prevent ODR violations when LTO is enabled. -} - -ComplexInput& ComplexInput::operator=(const ComplexInput& other) -{ - ComplexInput value { other }; - - std::swap(*this, value); - - return *this; -} - -ComplexInput& ComplexInput::operator=(ComplexInput&& other) noexcept -{ - name = std::move(other.name); - owner = std::move(other.owner); - - return *this; -} +namespace graphql::validation { Operations::Operations(std::shared_ptr query, std::shared_ptr mutation, std::shared_ptr subscription) : service::Request({ @@ -257,13 +79,15 @@ void AddTypesToSchema(const std::shared_ptr& schema) auto typeArguments = schema::ObjectType::Make(R"gql(Arguments)gql"sv, R"md()md"sv); schema->AddType(R"gql(Arguments)gql"sv, typeArguments); + static const auto s_namesDogCommand = getDogCommandNames(); typeDogCommand->AddEnumValues({ - { service::s_namesDogCommand[static_cast(validation::DogCommand::SIT)], R"md()md"sv, std::nullopt }, - { service::s_namesDogCommand[static_cast(validation::DogCommand::DOWN)], R"md()md"sv, std::nullopt }, - { service::s_namesDogCommand[static_cast(validation::DogCommand::HEEL)], R"md()md"sv, std::nullopt } + { s_namesDogCommand[static_cast(validation::DogCommand::SIT)], R"md()md"sv, std::nullopt }, + { s_namesDogCommand[static_cast(validation::DogCommand::DOWN)], R"md()md"sv, std::nullopt }, + { s_namesDogCommand[static_cast(validation::DogCommand::HEEL)], R"md()md"sv, std::nullopt } }); + static const auto s_namesCatCommand = getCatCommandNames(); typeCatCommand->AddEnumValues({ - { service::s_namesCatCommand[static_cast(validation::CatCommand::JUMP)], R"md()md"sv, std::nullopt } + { s_namesCatCommand[static_cast(validation::CatCommand::JUMP)], R"md()md"sv, std::nullopt } }); typeComplexInput->AddInputValues({ @@ -312,5 +136,4 @@ std::shared_ptr GetSchema() return schema; } -} // namespace validation -} // namespace graphql +} // namespace graphql::validation diff --git a/samples/validation/schema/ValidationSchema.h b/samples/validation/schema/ValidationSchema.h index 9f6be1d3..80d071f7 100644 --- a/samples/validation/schema/ValidationSchema.h +++ b/samples/validation/schema/ValidationSchema.h @@ -14,6 +14,8 @@ #include "graphqlservice/internal/Version.h" #include "graphqlservice/internal/Schema.h" +#include "ValidationSharedTypes.h" + #include #include #include @@ -23,78 +25,7 @@ static_assert(graphql::internal::MajorVersion == 5, "regenerate with schemagen: major version mismatch"); static_assert(graphql::internal::MinorVersion == 0, "regenerate with schemagen: minor version mismatch"); -namespace graphql { -namespace validation { - -enum class [[nodiscard("unnecessary conversion")]] DogCommand -{ - SIT, - DOWN, - HEEL -}; - -[[nodiscard("unnecessary call")]] constexpr auto getDogCommandNames() noexcept -{ - using namespace std::literals; - - return std::array { - R"gql(SIT)gql"sv, - R"gql(DOWN)gql"sv, - R"gql(HEEL)gql"sv - }; -} - -[[nodiscard("unnecessary call")]] constexpr auto getDogCommandValues() noexcept -{ - using namespace std::literals; - - return std::array, 3> { - std::make_pair(R"gql(SIT)gql"sv, DogCommand::SIT), - std::make_pair(R"gql(DOWN)gql"sv, DogCommand::DOWN), - std::make_pair(R"gql(HEEL)gql"sv, DogCommand::HEEL) - }; -} - -enum class [[nodiscard("unnecessary conversion")]] CatCommand -{ - JUMP -}; - -[[nodiscard("unnecessary call")]] constexpr auto getCatCommandNames() noexcept -{ - using namespace std::literals; - - return std::array { - R"gql(JUMP)gql"sv - }; -} - -[[nodiscard("unnecessary call")]] constexpr auto getCatCommandValues() noexcept -{ - using namespace std::literals; - - return std::array, 1> { - std::make_pair(R"gql(JUMP)gql"sv, CatCommand::JUMP) - }; -} - -struct [[nodiscard("unnecessary construction")]] ComplexInput -{ - explicit ComplexInput() noexcept; - explicit ComplexInput( - std::optional nameArg, - std::optional ownerArg) noexcept; - ComplexInput(const ComplexInput& other); - ComplexInput(ComplexInput&& other) noexcept; - ~ComplexInput(); - - ComplexInput& operator=(const ComplexInput& other); - ComplexInput& operator=(ComplexInput&& other) noexcept; - - std::optional name; - std::optional owner; -}; - +namespace graphql::validation { namespace object { class Sentient; @@ -163,7 +94,6 @@ void AddArgumentsDetails(const std::shared_ptr& typeArgument std::shared_ptr GetSchema(); -} // namespace validation -} // namespace graphql +} // namespace graphql::validation #endif // VALIDATIONSCHEMA_H diff --git a/samples/validation/schema/ValidationSchema.ixx b/samples/validation/schema/ValidationSchema.ixx index 0501c3ec..32a656ad 100644 --- a/samples/validation/schema/ValidationSchema.ixx +++ b/samples/validation/schema/ValidationSchema.ixx @@ -9,6 +9,8 @@ module; export module GraphQL.Validation.ValidationSchema; +export import GraphQL.Validation.ValidationSharedTypes; + export import GraphQL.Validation.SentientObject; export import GraphQL.Validation.PetObject; export import GraphQL.Validation.NodeObject; @@ -29,16 +31,6 @@ export import GraphQL.Validation.ArgumentsObject; export namespace graphql::validation { -using validation::DogCommand; -using validation::getDogCommandNames; -using validation::getDogCommandValues; - -using validation::CatCommand; -using validation::getCatCommandNames; -using validation::getCatCommandValues; - -using validation::ComplexInput; - using validation::Operations; using validation::AddSentientDetails; diff --git a/samples/validation/schema/ValidationSharedTypes.cpp b/samples/validation/schema/ValidationSharedTypes.cpp new file mode 100644 index 00000000..47c18527 --- /dev/null +++ b/samples/validation/schema/ValidationSharedTypes.cpp @@ -0,0 +1,202 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// WARNING! Do not edit this file manually, your changes will be overwritten. + +#include "graphqlservice/GraphQLService.h" + +#include "ValidationSharedTypes.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std::literals; + +namespace graphql { +namespace service { + +static const auto s_namesDogCommand = validation::getDogCommandNames(); +static const auto s_valuesDogCommand = validation::getDogCommandValues(); + +template <> +validation::DogCommand Argument::convert(const response::Value& value) +{ + if (!value.maybe_enum()) + { + throw service::schema_exception { { R"ex(not a valid DogCommand value)ex" } }; + } + + const auto result = internal::sorted_map_lookup( + s_valuesDogCommand, + std::string_view { value.get() }); + + if (!result) + { + throw service::schema_exception { { R"ex(not a valid DogCommand value)ex" } }; + } + + return *result; +} + +template <> +service::AwaitableResolver Result::convert(service::AwaitableScalar result, ResolverParams&& params) +{ + return ModifiedResult::resolve(std::move(result), std::move(params), + [](validation::DogCommand value, const ResolverParams&) + { + response::Value resolvedResult(response::Type::EnumValue); + + resolvedResult.set(std::string { s_namesDogCommand[static_cast(value)] }); + + return resolvedResult; + }); +} + +template <> +void Result::validateScalar(const response::Value& value) +{ + if (!value.maybe_enum()) + { + throw service::schema_exception { { R"ex(not a valid DogCommand value)ex" } }; + } + + const auto [itr, itrEnd] = internal::sorted_map_equal_range( + s_valuesDogCommand.begin(), + s_valuesDogCommand.end(), + std::string_view { value.get() }); + + if (itr == itrEnd) + { + throw service::schema_exception { { R"ex(not a valid DogCommand value)ex" } }; + } +} + +static const auto s_namesCatCommand = validation::getCatCommandNames(); +static const auto s_valuesCatCommand = validation::getCatCommandValues(); + +template <> +validation::CatCommand Argument::convert(const response::Value& value) +{ + if (!value.maybe_enum()) + { + throw service::schema_exception { { R"ex(not a valid CatCommand value)ex" } }; + } + + const auto result = internal::sorted_map_lookup( + s_valuesCatCommand, + std::string_view { value.get() }); + + if (!result) + { + throw service::schema_exception { { R"ex(not a valid CatCommand value)ex" } }; + } + + return *result; +} + +template <> +service::AwaitableResolver Result::convert(service::AwaitableScalar result, ResolverParams&& params) +{ + return ModifiedResult::resolve(std::move(result), std::move(params), + [](validation::CatCommand value, const ResolverParams&) + { + response::Value resolvedResult(response::Type::EnumValue); + + resolvedResult.set(std::string { s_namesCatCommand[static_cast(value)] }); + + return resolvedResult; + }); +} + +template <> +void Result::validateScalar(const response::Value& value) +{ + if (!value.maybe_enum()) + { + throw service::schema_exception { { R"ex(not a valid CatCommand value)ex" } }; + } + + const auto [itr, itrEnd] = internal::sorted_map_equal_range( + s_valuesCatCommand.begin(), + s_valuesCatCommand.end(), + std::string_view { value.get() }); + + if (itr == itrEnd) + { + throw service::schema_exception { { R"ex(not a valid CatCommand value)ex" } }; + } +} + +template <> +validation::ComplexInput Argument::convert(const response::Value& value) +{ + auto valueName = service::ModifiedArgument::require("name", value); + auto valueOwner = service::ModifiedArgument::require("owner", value); + + return validation::ComplexInput { + std::move(valueName), + std::move(valueOwner) + }; +} + +} // namespace service + +namespace validation { + +ComplexInput::ComplexInput() noexcept + : name {} + , owner {} +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +ComplexInput::ComplexInput( + std::optional nameArg, + std::optional ownerArg) noexcept + : name { std::move(nameArg) } + , owner { std::move(ownerArg) } +{ +} + +ComplexInput::ComplexInput(const ComplexInput& other) + : name { service::ModifiedArgument::duplicate(other.name) } + , owner { service::ModifiedArgument::duplicate(other.owner) } +{ +} + +ComplexInput::ComplexInput(ComplexInput&& other) noexcept + : name { std::move(other.name) } + , owner { std::move(other.owner) } +{ +} + +ComplexInput::~ComplexInput() +{ + // Explicit definition to prevent ODR violations when LTO is enabled. +} + +ComplexInput& ComplexInput::operator=(const ComplexInput& other) +{ + ComplexInput value { other }; + + std::swap(*this, value); + + return *this; +} + +ComplexInput& ComplexInput::operator=(ComplexInput&& other) noexcept +{ + name = std::move(other.name); + owner = std::move(other.owner); + + return *this; +} + +} // namespace validation +} // namespace graphql diff --git a/samples/validation/schema/ValidationSharedTypes.h b/samples/validation/schema/ValidationSharedTypes.h new file mode 100644 index 00000000..7b963d0a --- /dev/null +++ b/samples/validation/schema/ValidationSharedTypes.h @@ -0,0 +1,101 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// WARNING! Do not edit this file manually, your changes will be overwritten. + +#pragma once + +#ifndef VALIDATIONSHAREDTYPES_H +#define VALIDATIONSHAREDTYPES_H + +#include "graphqlservice/GraphQLResponse.h" + +#include "graphqlservice/internal/Version.h" + +#include +#include +#include +#include +#include +#include + +// Check if the library version is compatible with schemagen 5.0.0 +static_assert(graphql::internal::MajorVersion == 5, "regenerate with schemagen: major version mismatch"); +static_assert(graphql::internal::MinorVersion == 0, "regenerate with schemagen: minor version mismatch"); + +namespace graphql { +namespace validation { + +enum class [[nodiscard("unnecessary conversion")]] DogCommand +{ + SIT, + DOWN, + HEEL +}; + +[[nodiscard("unnecessary call")]] constexpr auto getDogCommandNames() noexcept +{ + using namespace std::literals; + + return std::array { + R"gql(SIT)gql"sv, + R"gql(DOWN)gql"sv, + R"gql(HEEL)gql"sv + }; +} + +[[nodiscard("unnecessary call")]] constexpr auto getDogCommandValues() noexcept +{ + using namespace std::literals; + + return std::array, 3> { + std::make_pair(R"gql(SIT)gql"sv, DogCommand::SIT), + std::make_pair(R"gql(DOWN)gql"sv, DogCommand::DOWN), + std::make_pair(R"gql(HEEL)gql"sv, DogCommand::HEEL) + }; +} + +enum class [[nodiscard("unnecessary conversion")]] CatCommand +{ + JUMP +}; + +[[nodiscard("unnecessary call")]] constexpr auto getCatCommandNames() noexcept +{ + using namespace std::literals; + + return std::array { + R"gql(JUMP)gql"sv + }; +} + +[[nodiscard("unnecessary call")]] constexpr auto getCatCommandValues() noexcept +{ + using namespace std::literals; + + return std::array, 1> { + std::make_pair(R"gql(JUMP)gql"sv, CatCommand::JUMP) + }; +} + +struct [[nodiscard("unnecessary construction")]] ComplexInput +{ + explicit ComplexInput() noexcept; + explicit ComplexInput( + std::optional nameArg, + std::optional ownerArg) noexcept; + ComplexInput(const ComplexInput& other); + ComplexInput(ComplexInput&& other) noexcept; + ~ComplexInput(); + + ComplexInput& operator=(const ComplexInput& other); + ComplexInput& operator=(ComplexInput&& other) noexcept; + + std::optional name; + std::optional owner; +}; + +} // namespace validation +} // namespace graphql + +#endif // VALIDATIONSHAREDTYPES_H diff --git a/samples/validation/schema/ValidationSharedTypes.ixx b/samples/validation/schema/ValidationSharedTypes.ixx new file mode 100644 index 00000000..9dbcfe15 --- /dev/null +++ b/samples/validation/schema/ValidationSharedTypes.ixx @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// WARNING! Do not edit this file manually, your changes will be overwritten. + +module; + +#include "ValidationSharedTypes.h" + +export module GraphQL.Validation.ValidationSharedTypes; + +export namespace graphql::validation { + +using validation::DogCommand; +using validation::getDogCommandNames; +using validation::getDogCommandValues; + +using validation::CatCommand; +using validation::getCatCommandNames; +using validation::getCatCommandValues; + +using validation::ComplexInput; + +} // namespace graphql::validation diff --git a/samples/validation/schema/validation_schema_files b/samples/validation/schema/validation_schema_files index 60750fdd..f091b606 100644 --- a/samples/validation/schema/validation_schema_files +++ b/samples/validation/schema/validation_schema_files @@ -1,3 +1,4 @@ +ValidationSharedTypes.cpp ValidationSchema.cpp SentientObject.cpp PetObject.cpp diff --git a/src/ClientGenerator.cpp b/src/ClientGenerator.cpp index 69ba95ba..3b37757e 100644 --- a/src/ClientGenerator.cpp +++ b/src/ClientGenerator.cpp @@ -198,7 +198,7 @@ bool Generator::outputHeader() const noexcept { headerFile << R"cpp( #include ")cpp" << _schemaLoader.getFilenamePrefix() - << R"cpp(Schema.h" + << R"cpp(SharedTypes.h" )cpp"; } @@ -1640,7 +1640,7 @@ int main(int argc, char** argv) po::bool_switch(&noIntrospection), "Do not expect support for Introspection")("shared-types", po::bool_switch(&sharedTypes), - "Re-use shared types from Schema.h"); + "Re-use shared types from SharedTypes.h"); positional.add("schema", 1).add("request", 1).add("prefix", 1).add("namespace", 1); try diff --git a/src/SchemaGenerator.cpp b/src/SchemaGenerator.cpp index 7bf1af1d..1a62684a 100644 --- a/src/SchemaGenerator.cpp +++ b/src/SchemaGenerator.cpp @@ -40,9 +40,12 @@ Generator::Generator(SchemaOptions&& schemaOptions, GeneratorOptions&& options) , _options(std::move(options)) , _headerDir(getHeaderDir()) , _sourceDir(getSourceDir()) - , _headerPath(getHeaderPath()) - , _modulePath(getModulePath()) - , _sourcePath(getSourcePath()) + , _schemaHeaderPath(getSchemaHeaderPath()) + , _schemaModulePath(getSchemaModulePath()) + , _schemaSourcePath(getSchemaSourcePath()) + , _sharedTypesHeaderPath(getSharedTypesHeaderPath()) + , _sharedTypesModulePath(getSharedTypesModulePath()) + , _sharedTypesSourcePath(getSharedTypesSourcePath()) { } @@ -70,7 +73,7 @@ std::string Generator::getSourceDir() const noexcept } } -std::string Generator::getHeaderPath() const noexcept +std::string Generator::getSchemaHeaderPath() const noexcept { std::filesystem::path fullPath { _headerDir }; @@ -78,7 +81,7 @@ std::string Generator::getHeaderPath() const noexcept return fullPath.string(); } -std::string Generator::getModulePath() const noexcept +std::string Generator::getSchemaModulePath() const noexcept { std::filesystem::path fullPath { _headerDir }; @@ -86,7 +89,7 @@ std::string Generator::getModulePath() const noexcept return fullPath.string(); } -std::string Generator::getSourcePath() const noexcept +std::string Generator::getSchemaSourcePath() const noexcept { std::filesystem::path fullPath { _sourceDir }; @@ -94,23 +97,62 @@ std::string Generator::getSourcePath() const noexcept return fullPath.string(); } +std::string Generator::getSharedTypesHeaderPath() const noexcept +{ + std::filesystem::path fullPath { _headerDir }; + + fullPath /= (std::string { _loader.getFilenamePrefix() } + "SharedTypes.h"); + return fullPath.string(); +} + +std::string Generator::getSharedTypesModulePath() const noexcept +{ + std::filesystem::path fullPath { _headerDir }; + + fullPath /= (std::string { _loader.getFilenamePrefix() } + "SharedTypes.ixx"); + return fullPath.string(); +} + +std::string Generator::getSharedTypesSourcePath() const noexcept +{ + std::filesystem::path fullPath { _sourceDir }; + + fullPath /= (std::string { _loader.getFilenamePrefix() } + "SharedTypes.cpp"); + return fullPath.string(); +} + std::vector Generator::Build() const noexcept { std::vector builtFiles; - if (outputHeader() && _options.verbose) + if (outputSharedTypesHeader() && _options.verbose) + { + builtFiles.push_back(_sharedTypesHeaderPath); + } + + if (outputSharedTypesModule() && _options.verbose) + { + builtFiles.push_back(_sharedTypesModulePath); + } + + if (outputSchemaHeader() && _options.verbose) { - builtFiles.push_back(_headerPath); + builtFiles.push_back(_schemaHeaderPath); } - if (outputModule() && _options.verbose) + if (outputSchemaModule() && _options.verbose) { - builtFiles.push_back(_modulePath); + builtFiles.push_back(_schemaModulePath); } - if (outputSource()) + if (outputSharedTypesSource()) { - builtFiles.push_back(_sourcePath); + builtFiles.push_back(_sharedTypesSourcePath); + } + + if (outputSchemaSource()) + { + builtFiles.push_back(_schemaSourcePath); } auto separateFiles = outputSeparateFiles(); @@ -123,18 +165,36 @@ std::vector Generator::Build() const noexcept return builtFiles; } -bool Generator::outputHeader() const noexcept +bool Generator::outputSchemaHeader() const noexcept { - std::ofstream headerFile(_headerPath, std::ios_base::trunc); + std::ofstream headerFile(_schemaHeaderPath, std::ios_base::trunc); IncludeGuardScope includeGuard { headerFile, - std::filesystem::path(_headerPath).filename().string() }; + std::filesystem::path(_schemaHeaderPath).filename().string() }; headerFile << R"cpp(#include "graphqlservice/GraphQLResponse.h" #include "graphqlservice/GraphQLService.h" -#include "graphqlservice/internal/Version.h" +)cpp"; + + if (_loader.isIntrospection()) + { + headerFile << R"cpp(#include "graphqlservice/internal/DllExports.h" +)cpp"; + } + + headerFile << R"cpp(#include "graphqlservice/internal/Version.h" #include "graphqlservice/internal/Schema.h" +)cpp"; + + if (!_loader.getEnumTypes().empty() || !_loader.getInputTypes().empty()) + { + headerFile << R"cpp( +#include ")cpp" << _loader.getFilenamePrefix() + << R"cpp(SharedTypes.h" +)cpp"; + } + headerFile << R"cpp( #include #include #include @@ -152,214 +212,11 @@ static_assert(graphql::internal::MinorVersion == )cpp" )cpp"; - NamespaceScope graphqlNamespace { headerFile, "graphql" }; - NamespaceScope schemaNamespace { headerFile, _loader.getSchemaNamespace() }; + const auto schemaNamespace = std::format(R"cpp(graphql::{})cpp", _loader.getSchemaNamespace()); + NamespaceScope schemaNamespaceScope { headerFile, schemaNamespace }; NamespaceScope objectNamespace { headerFile, "object", true }; PendingBlankLine pendingSeparator { headerFile }; - if (!_loader.getEnumTypes().empty()) - { - pendingSeparator.reset(); - - for (const auto& enumType : _loader.getEnumTypes()) - { - headerFile << R"cpp(enum class )cpp"; - - if (!_loader.isIntrospection()) - { - headerFile << R"cpp([[nodiscard("unnecessary conversion")]] )cpp"; - } - - headerFile << enumType.cppType << R"cpp( -{ -)cpp"; - - bool firstValue = true; - - for (const auto& value : enumType.values) - { - if (!firstValue) - { - headerFile << R"cpp(, -)cpp"; - } - - firstValue = false; - headerFile << R"cpp( )cpp" << value.cppValue; - } - headerFile << R"cpp( -}; - -)cpp"; - - headerFile << R"cpp([[nodiscard("unnecessary call")]] constexpr auto get)cpp" - << enumType.cppType << R"cpp(Names() noexcept -{ - using namespace std::literals; - - return std::array { -)cpp"; - - firstValue = true; - - for (const auto& value : enumType.values) - { - if (!firstValue) - { - headerFile << R"cpp(, -)cpp"; - } - - firstValue = false; - headerFile << R"cpp( R"gql()cpp" << value.value << R"cpp()gql"sv)cpp"; - } - - headerFile << R"cpp( - }; -} - -[[nodiscard("unnecessary call")]] constexpr auto get)cpp" - << enumType.cppType << R"cpp(Values() noexcept -{ - using namespace std::literals; - - return std::array, )cpp" << enumType.values.size() << R"cpp(> { -)cpp"; - - std::vector> sortedValues( - enumType.values.size()); - - std::ranges::transform(enumType.values, - sortedValues.begin(), - [](const auto& value) noexcept { - return std::make_pair(value.value, value.cppValue); - }); - std::ranges::sort(sortedValues, [](const auto& lhs, const auto& rhs) noexcept { - return internal::shorter_or_less {}(lhs.first, rhs.first); - }); - - firstValue = true; - - for (const auto& [enumName, enumValue] : sortedValues) - { - if (!firstValue) - { - headerFile << R"cpp(, -)cpp"; - } - - firstValue = false; - headerFile << R"cpp( std::make_pair(R"gql()cpp" << enumName - << R"cpp()gql"sv, )cpp" << enumType.cppType << R"cpp(::)cpp" << enumValue - << R"cpp())cpp"; - } - - headerFile << R"cpp( - }; -} - -)cpp"; - } - } - - if (!_loader.getInputTypes().empty()) - { - pendingSeparator.reset(); - - std::unordered_set forwardDeclared; - const auto introspectionExport = - (_loader.isIntrospection() ? "GRAPHQLSERVICE_EXPORT "sv : ""sv); - - // Output the full declarations - for (const auto& inputType : _loader.getInputTypes()) - { - forwardDeclared.insert(inputType.cppType); - - if (!inputType.declarations.empty()) - { - // Forward declare nullable dependencies - for (auto declaration : inputType.declarations) - { - if (forwardDeclared.insert(declaration).second) - { - headerFile << R"cpp(struct )cpp" << declaration << R"cpp(; -)cpp"; - pendingSeparator.add(); - } - } - - pendingSeparator.reset(); - } - - headerFile << R"cpp(struct [[nodiscard("unnecessary construction")]] )cpp" - << inputType.cppType << R"cpp( -{ - )cpp" << introspectionExport - << R"cpp(explicit )cpp" << inputType.cppType << R"cpp(()cpp"; - - bool firstField = true; - - for (const auto& inputField : inputType.fields) - { - if (firstField) - { - headerFile << R"cpp() noexcept; - explicit )cpp" << inputType.cppType - << R"cpp(()cpp"; - } - else - { - headerFile << R"cpp(,)cpp"; - } - - firstField = false; - - const auto inputCppType = _loader.getInputCppType(inputField); - - headerFile << R"cpp( - )cpp" << inputCppType - << R"cpp( )cpp" << inputField.cppName << R"cpp(Arg)cpp"; - } - - headerFile << R"cpp() noexcept; - )cpp" << introspectionExport - << inputType.cppType << R"cpp((const )cpp" << inputType.cppType - << R"cpp(& other); - )cpp" << introspectionExport - << inputType.cppType << R"cpp(()cpp" << inputType.cppType - << R"cpp(&& other) noexcept; - ~)cpp" << inputType.cppType - << R"cpp((); - - )cpp" << introspectionExport - << inputType.cppType << R"cpp(& operator=(const )cpp" << inputType.cppType - << R"cpp(& other); - )cpp" << introspectionExport - << inputType.cppType << R"cpp(& operator=()cpp" << inputType.cppType - << R"cpp(&& other) noexcept; -)cpp"; - - firstField = true; - - for (const auto& inputField : inputType.fields) - { - if (firstField) - { - headerFile << std::endl; - } - - firstField = false; - - headerFile << getFieldDeclaration(inputField); - } - headerFile << R"cpp(}; - -)cpp"; - } - } - if (!_loader.getInterfaceTypes().empty()) { objectNamespace.enter(); @@ -600,70 +457,16 @@ static_assert(graphql::internal::MinorVersion == )cpp" headerFile << std::endl; } - NamespaceScope serviceNamespace { headerFile, "service", true }; - if (_loader.isIntrospection()) { headerFile << R"cpp(GRAPHQLSERVICE_EXPORT void AddTypesToSchema(const std::shared_ptr& schema); )cpp"; - - if (!_loader.getEnumTypes().empty() || !_loader.getInputTypes().empty()) - { - if (schemaNamespace.exit()) - { - headerFile << std::endl; - } - - serviceNamespace.enter(); - - headerFile << R"cpp( -#ifdef GRAPHQL_DLLEXPORTS -// Export all of the built-in converters -)cpp"; - - for (const auto& enumType : _loader.getEnumTypes()) - { - headerFile << R"cpp(template <> -GRAPHQLSERVICE_EXPORT )cpp" << _loader.getSchemaNamespace() - << R"cpp(::)cpp" << enumType.cppType << R"cpp( Argument<)cpp" - << _loader.getSchemaNamespace() << R"cpp(::)cpp" << enumType.cppType - << R"cpp(>::convert( - const response::Value& value); -template <> -GRAPHQLSERVICE_EXPORT AwaitableResolver Result<)cpp" - << _loader.getSchemaNamespace() << R"cpp(::)cpp" << enumType.cppType - << R"cpp(>::convert( - AwaitableScalar<)cpp" << _loader.getSchemaNamespace() - << R"cpp(::)cpp" << enumType.cppType - << R"cpp(> result, ResolverParams&& params); -template <> -GRAPHQLSERVICE_EXPORT void Result<)cpp" - << _loader.getSchemaNamespace() << R"cpp(::)cpp" << enumType.cppType - << R"cpp(>::validateScalar( - const response::Value& value); -)cpp"; - } - - for (const auto& inputType : _loader.getInputTypes()) - { - headerFile << R"cpp(template <> -GRAPHQLSERVICE_EXPORT )cpp" << _loader.getSchemaNamespace() - << R"cpp(::)cpp" << inputType.cppType << R"cpp( Argument<)cpp" - << inputType.cppType << R"cpp(>::convert( - const response::Value& value); -)cpp"; - } - - headerFile << R"cpp(#endif // GRAPHQL_DLLEXPORTS - -)cpp"; - } - } - else - { - headerFile << R"cpp(std::shared_ptr GetSchema(); + } + else + { + headerFile << R"cpp(std::shared_ptr GetSchema(); )cpp"; } @@ -671,9 +474,9 @@ GRAPHQLSERVICE_EXPORT )cpp" << _loader.getSchemaNamespace() return true; } -bool Generator::outputModule() const noexcept +bool Generator::outputSchemaModule() const noexcept { - std::ofstream moduleFile(_modulePath, std::ios_base::trunc); + std::ofstream moduleFile(_schemaModulePath, std::ios_base::trunc); const auto schemaNamespace = std::format(R"cpp(graphql::{})cpp", _loader.getSchemaNamespace()); moduleFile << R"cpp(// Copyright (c) Microsoft Corporation. All rights reserved. @@ -692,6 +495,15 @@ export module GraphQL.)cpp" R"cpp(Schema; )cpp"; + if (!_loader.getEnumTypes().empty() || !_loader.getInputTypes().empty()) + { + moduleFile << R"cpp( +export import GraphQL.)cpp" + << _loader.getFilenamePrefix() << R"cpp(.)cpp" << _loader.getFilenamePrefix() << + R"cpp(SharedTypes; +)cpp"; + } + PendingBlankLine pendingSeparator { moduleFile }; if (!_loader.getInterfaceTypes().empty()) @@ -737,37 +549,6 @@ export )cpp"; pendingSeparator.add(); - if (!_loader.getEnumTypes().empty()) - { - pendingSeparator.reset(); - - for (const auto& enumType : _loader.getEnumTypes()) - { - moduleFile << R"cpp(using )cpp" << _loader.getSchemaNamespace() << R"cpp(::)cpp" - << enumType.cppType << R"cpp(; -using )cpp" << _loader.getSchemaNamespace() - << R"cpp(::get)cpp" << enumType.cppType << R"cpp(Names; -using )cpp" << _loader.getSchemaNamespace() - << R"cpp(::get)cpp" << enumType.cppType << R"cpp(Values; - -)cpp"; - } - } - - if (!_loader.getInputTypes().empty()) - { - pendingSeparator.reset(); - - for (const auto& inputType : _loader.getInputTypes()) - { - moduleFile << R"cpp(using )cpp" << _loader.getSchemaNamespace() << R"cpp(::)cpp" - << inputType.cppType << R"cpp(; -)cpp"; - } - - moduleFile << std::endl; - } - if (!_loader.isIntrospection()) { pendingSeparator.reset(); @@ -833,6 +614,381 @@ using )cpp" << _loader.getSchemaNamespace() return true; } +bool Generator::outputSharedTypesHeader() const noexcept +{ + if (_loader.getEnumTypes().empty() && _loader.getInputTypes().empty()) + { + return false; + } + + std::ofstream headerFile(_sharedTypesHeaderPath, std::ios_base::trunc); + IncludeGuardScope includeGuard { headerFile, + std::filesystem::path(_sharedTypesHeaderPath).filename().string() }; + + headerFile << R"cpp(#include "graphqlservice/GraphQLResponse.h" + +)cpp"; + + if (_loader.isIntrospection()) + { + headerFile << R"cpp(#include "graphqlservice/internal/DllExports.h" +)cpp"; + } + + headerFile << R"cpp(#include "graphqlservice/internal/Version.h" + +#include +#include +#include +#include +#include +#include + +// Check if the library version is compatible with schemagen )cpp" + << graphql::internal::MajorVersion << R"cpp(.)cpp" << graphql::internal::MinorVersion + << R"cpp(.0 +static_assert(graphql::internal::MajorVersion == )cpp" + << graphql::internal::MajorVersion + << R"cpp(, "regenerate with schemagen: major version mismatch"); +static_assert(graphql::internal::MinorVersion == )cpp" + << graphql::internal::MinorVersion + << R"cpp(, "regenerate with schemagen: minor version mismatch"); + +)cpp"; + + NamespaceScope graphqlNamespace { headerFile, "graphql" }; + NamespaceScope schemaNamespace { headerFile, _loader.getSchemaNamespace() }; + PendingBlankLine pendingSeparator { headerFile }; + + if (!_loader.getEnumTypes().empty()) + { + pendingSeparator.reset(); + + for (const auto& enumType : _loader.getEnumTypes()) + { + headerFile << R"cpp(enum class )cpp"; + + if (!_loader.isIntrospection()) + { + headerFile << R"cpp([[nodiscard("unnecessary conversion")]] )cpp"; + } + + headerFile << enumType.cppType << R"cpp( +{ +)cpp"; + + bool firstValue = true; + + for (const auto& value : enumType.values) + { + if (!firstValue) + { + headerFile << R"cpp(, +)cpp"; + } + + firstValue = false; + headerFile << R"cpp( )cpp" << value.cppValue; + } + headerFile << R"cpp( +}; + +)cpp"; + + headerFile << R"cpp([[nodiscard("unnecessary call")]] constexpr auto get)cpp" + << enumType.cppType << R"cpp(Names() noexcept +{ + using namespace std::literals; + + return std::array { +)cpp"; + + firstValue = true; + + for (const auto& value : enumType.values) + { + if (!firstValue) + { + headerFile << R"cpp(, +)cpp"; + } + + firstValue = false; + headerFile << R"cpp( R"gql()cpp" << value.value << R"cpp()gql"sv)cpp"; + } + + headerFile << R"cpp( + }; +} + +[[nodiscard("unnecessary call")]] constexpr auto get)cpp" + << enumType.cppType << R"cpp(Values() noexcept +{ + using namespace std::literals; + + return std::array, )cpp" << enumType.values.size() << R"cpp(> { +)cpp"; + + std::vector> sortedValues( + enumType.values.size()); + + std::ranges::transform(enumType.values, + sortedValues.begin(), + [](const auto& value) noexcept { + return std::make_pair(value.value, value.cppValue); + }); + std::ranges::sort(sortedValues, [](const auto& lhs, const auto& rhs) noexcept { + return internal::shorter_or_less {}(lhs.first, rhs.first); + }); + + firstValue = true; + + for (const auto& [enumName, enumValue] : sortedValues) + { + if (!firstValue) + { + headerFile << R"cpp(, +)cpp"; + } + + firstValue = false; + headerFile << R"cpp( std::make_pair(R"gql()cpp" << enumName + << R"cpp()gql"sv, )cpp" << enumType.cppType << R"cpp(::)cpp" << enumValue + << R"cpp())cpp"; + } + + headerFile << R"cpp( + }; +} + +)cpp"; + } + } + + if (!_loader.getInputTypes().empty()) + { + pendingSeparator.reset(); + + std::unordered_set forwardDeclared; + const auto introspectionExport = + (_loader.isIntrospection() ? "GRAPHQLSERVICE_EXPORT "sv : ""sv); + + // Output the full declarations + for (const auto& inputType : _loader.getInputTypes()) + { + forwardDeclared.insert(inputType.cppType); + + if (!inputType.declarations.empty()) + { + // Forward declare nullable dependencies + for (auto declaration : inputType.declarations) + { + if (forwardDeclared.insert(declaration).second) + { + headerFile << R"cpp(struct )cpp" << declaration << R"cpp(; +)cpp"; + pendingSeparator.add(); + } + } + + pendingSeparator.reset(); + } + + headerFile << R"cpp(struct [[nodiscard("unnecessary construction")]] )cpp" + << inputType.cppType << R"cpp( +{ + )cpp" << introspectionExport + << R"cpp(explicit )cpp" << inputType.cppType << R"cpp(()cpp"; + + bool firstField = true; + + for (const auto& inputField : inputType.fields) + { + if (firstField) + { + headerFile << R"cpp() noexcept; + explicit )cpp" << inputType.cppType + << R"cpp(()cpp"; + } + else + { + headerFile << R"cpp(,)cpp"; + } + + firstField = false; + + const auto inputCppType = _loader.getInputCppType(inputField); + + headerFile << R"cpp( + )cpp" << inputCppType + << R"cpp( )cpp" << inputField.cppName << R"cpp(Arg)cpp"; + } + + headerFile << R"cpp() noexcept; + )cpp" << introspectionExport + << inputType.cppType << R"cpp((const )cpp" << inputType.cppType + << R"cpp(& other); + )cpp" << introspectionExport + << inputType.cppType << R"cpp(()cpp" << inputType.cppType + << R"cpp(&& other) noexcept; + ~)cpp" << inputType.cppType + << R"cpp((); + + )cpp" << introspectionExport + << inputType.cppType << R"cpp(& operator=(const )cpp" << inputType.cppType + << R"cpp(& other); + )cpp" << introspectionExport + << inputType.cppType << R"cpp(& operator=()cpp" << inputType.cppType + << R"cpp(&& other) noexcept; +)cpp"; + + firstField = true; + + for (const auto& inputField : inputType.fields) + { + if (firstField) + { + headerFile << std::endl; + } + + firstField = false; + + headerFile << getFieldDeclaration(inputField); + } + headerFile << R"cpp(}; + +)cpp"; + } + } + + if (_loader.isIntrospection()) + { + if (schemaNamespace.exit()) + { + pendingSeparator.add(); + } + + pendingSeparator.reset(); + + NamespaceScope serviceNamespace { headerFile, "service" }; + + headerFile << R"cpp( +#ifdef GRAPHQL_DLLEXPORTS +// Export all of the built-in converters +)cpp"; + + for (const auto& enumType : _loader.getEnumTypes()) + { + headerFile << R"cpp(template <> +GRAPHQLSERVICE_EXPORT )cpp" + << _loader.getSchemaNamespace() << R"cpp(::)cpp" << enumType.cppType + << R"cpp( Argument<)cpp" << _loader.getSchemaNamespace() << R"cpp(::)cpp" + << enumType.cppType << R"cpp(>::convert( + const response::Value& value); +template <> +GRAPHQLSERVICE_EXPORT AwaitableResolver Result<)cpp" + << _loader.getSchemaNamespace() << R"cpp(::)cpp" << enumType.cppType + << R"cpp(>::convert( + AwaitableScalar<)cpp" + << _loader.getSchemaNamespace() << R"cpp(::)cpp" << enumType.cppType + << R"cpp(> result, ResolverParams&& params); +template <> +GRAPHQLSERVICE_EXPORT void Result<)cpp" + << _loader.getSchemaNamespace() << R"cpp(::)cpp" << enumType.cppType + << R"cpp(>::validateScalar( + const response::Value& value); +)cpp"; + } + + for (const auto& inputType : _loader.getInputTypes()) + { + headerFile << R"cpp(template <> +GRAPHQLSERVICE_EXPORT )cpp" + << _loader.getSchemaNamespace() << R"cpp(::)cpp" << inputType.cppType + << R"cpp( Argument<)cpp" << inputType.cppType << R"cpp(>::convert( + const response::Value& value); +)cpp"; + } + + headerFile << R"cpp(#endif // GRAPHQL_DLLEXPORTS + +)cpp"; + } + + return true; +} + +bool Generator::outputSharedTypesModule() const noexcept +{ + if (_loader.getEnumTypes().empty() && _loader.getInputTypes().empty()) + { + return false; + } + + std::ofstream moduleFile(_sharedTypesModulePath, std::ios_base::trunc); + const auto schemaNamespace = std::format(R"cpp(graphql::{})cpp", _loader.getSchemaNamespace()); + + moduleFile << R"cpp(// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// WARNING! Do not edit this file manually, your changes will be overwritten. + +module; + +#include ")cpp" << _loader.getFilenamePrefix() + << + R"cpp(SharedTypes.h" + +export module GraphQL.)cpp" + << _loader.getFilenamePrefix() << R"cpp(.)cpp" << _loader.getFilenamePrefix() << + R"cpp(SharedTypes; +)cpp"; + + PendingBlankLine pendingSeparator { moduleFile }; + + moduleFile << R"cpp( +export )cpp"; + + NamespaceScope graphqlNamespace { moduleFile, schemaNamespace }; + + pendingSeparator.add(); + + if (!_loader.getEnumTypes().empty()) + { + pendingSeparator.reset(); + + for (const auto& enumType : _loader.getEnumTypes()) + { + moduleFile << R"cpp(using )cpp" << _loader.getSchemaNamespace() << R"cpp(::)cpp" + << enumType.cppType << R"cpp(; +using )cpp" << _loader.getSchemaNamespace() + << R"cpp(::get)cpp" << enumType.cppType << R"cpp(Names; +using )cpp" << _loader.getSchemaNamespace() + << R"cpp(::get)cpp" << enumType.cppType << R"cpp(Values; + +)cpp"; + } + } + + if (!_loader.getInputTypes().empty()) + { + pendingSeparator.reset(); + + for (const auto& inputType : _loader.getInputTypes()) + { + moduleFile << R"cpp(using )cpp" << _loader.getSchemaNamespace() << R"cpp(::)cpp" + << inputType.cppType << R"cpp(; +)cpp"; + } + + moduleFile << std::endl; + } + + return true; +} + void Generator::outputInterfaceDeclaration(std::ostream& headerFile, std::string_view cppType) const { headerFile @@ -1434,60 +1590,34 @@ std::string Generator::getFieldDeclaration(const OutputField& outputField) const } std::string Generator::getResolverDeclaration(const OutputField& outputField) const noexcept -{ - const auto resolverName = SchemaLoader::getOutputCppResolver(outputField); - - return std::format( - R"cpp( [[nodiscard("unnecessary call")]] service::AwaitableResolver {}(service::ResolverParams&& params) const; -)cpp", - resolverName); -} - -bool Generator::outputSource() const noexcept -{ - std::ofstream sourceFile(_sourcePath, std::ios_base::trunc); - - sourceFile << R"cpp(// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -// WARNING! Do not edit this file manually, your changes will be overwritten. - -)cpp"; - - if (!_loader.isIntrospection()) - { - if (_loader.getOperationTypes().empty()) - { - // Normally this would be included by each of the operation object headers. - sourceFile << R"cpp(#include ")cpp" << getHeaderPath() << R"cpp(" -)cpp"; - } - else - { - for (const auto& operation : _loader.getOperationTypes()) - { - sourceFile << R"cpp(#include ")cpp" << operation.cppType << R"cpp(Object.h" -)cpp"; - } - } +{ + const auto resolverName = SchemaLoader::getOutputCppResolver(outputField); - sourceFile << std::endl; - } + return std::format( + R"cpp( [[nodiscard("unnecessary call")]] service::AwaitableResolver {}(service::ResolverParams&& params) const; +)cpp", + resolverName); +} - if (_loader.isIntrospection()) +bool Generator::outputSharedTypesSource() const noexcept +{ + if (_loader.getEnumTypes().empty() && _loader.getInputTypes().empty()) { - sourceFile << R"cpp(#include "graphqlservice/internal/Introspection.h" -)cpp"; + return false; } - else - { - sourceFile << R"cpp(#include "graphqlservice/internal/Schema.h" -#include "graphqlservice/introspection/IntrospectionSchema.h" -)cpp"; - } + std::ofstream sourceFile(_sharedTypesSourcePath, std::ios_base::trunc); + + sourceFile << R"cpp(// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// WARNING! Do not edit this file manually, your changes will be overwritten. + +#include "graphqlservice/GraphQLService.h" + +#include ")cpp" << getSharedTypesHeaderPath() + << R"cpp(" - sourceFile << R"cpp( #include #include #include @@ -1502,43 +1632,41 @@ using namespace std::literals; )cpp"; NamespaceScope graphqlNamespace { sourceFile, "graphql" }; + NamespaceScope serviceNamespace { sourceFile, "service" }; + PendingBlankLine pendingSeparator { sourceFile }; - if (!_loader.getEnumTypes().empty() || !_loader.getInputTypes().empty()) - { - NamespaceScope serviceNamespace { sourceFile, "service" }; - - sourceFile << std::endl; + pendingSeparator.reset(); - for (const auto& enumType : _loader.getEnumTypes()) - { - sourceFile << R"cpp(static const auto s_names)cpp" << enumType.cppType << R"cpp( = )cpp" - << _loader.getSchemaNamespace() << R"cpp(::get)cpp" << enumType.cppType - << R"cpp(Names(); + for (const auto& enumType : _loader.getEnumTypes()) + { + sourceFile << R"cpp(static const auto s_names)cpp" << enumType.cppType << R"cpp( = )cpp" + << _loader.getSchemaNamespace() << R"cpp(::get)cpp" << enumType.cppType + << R"cpp(Names(); static const auto s_values)cpp" - << enumType.cppType << R"cpp( = )cpp" << _loader.getSchemaNamespace() - << R"cpp(::get)cpp" << enumType.cppType << R"cpp(Values(); + << enumType.cppType << R"cpp( = )cpp" << _loader.getSchemaNamespace() + << R"cpp(::get)cpp" << enumType.cppType << R"cpp(Values(); template <> )cpp" << _loader.getSchemaNamespace() - << R"cpp(::)cpp" << enumType.cppType << R"cpp( Argument<)cpp" - << _loader.getSchemaNamespace() << R"cpp(::)cpp" << enumType.cppType - << R"cpp(>::convert(const response::Value& value) + << R"cpp(::)cpp" << enumType.cppType << R"cpp( Argument<)cpp" + << _loader.getSchemaNamespace() << R"cpp(::)cpp" << enumType.cppType + << R"cpp(>::convert(const response::Value& value) { if (!value.maybe_enum()) { throw service::schema_exception { { R"ex(not a valid )cpp" - << enumType.type << R"cpp( value)ex" } }; + << enumType.type << R"cpp( value)ex" } }; } const auto result = internal::sorted_map_lookup( - s_values)cpp" << enumType.cppType - << R"cpp(, + s_values)cpp" + << enumType.cppType << R"cpp(, std::string_view { value.get() }); if (!result) { throw service::schema_exception { { R"ex(not a valid )cpp" - << enumType.type << R"cpp( value)ex" } }; + << enumType.type << R"cpp( value)ex" } }; } return *result; @@ -1546,21 +1674,21 @@ template <> template <> service::AwaitableResolver Result<)cpp" - << _loader.getSchemaNamespace() << R"cpp(::)cpp" << enumType.cppType - << R"cpp(>::convert(service::AwaitableScalar<)cpp" - << _loader.getSchemaNamespace() << R"cpp(::)cpp" << enumType.cppType - << R"cpp(> result, ResolverParams&& params) + << _loader.getSchemaNamespace() << R"cpp(::)cpp" << enumType.cppType + << R"cpp(>::convert(service::AwaitableScalar<)cpp" + << _loader.getSchemaNamespace() << R"cpp(::)cpp" << enumType.cppType + << R"cpp(> result, ResolverParams&& params) { return ModifiedResult<)cpp" - << _loader.getSchemaNamespace() << R"cpp(::)cpp" << enumType.cppType - << R"cpp(>::resolve(std::move(result), std::move(params), + << _loader.getSchemaNamespace() << R"cpp(::)cpp" << enumType.cppType + << R"cpp(>::resolve(std::move(result), std::move(params), []()cpp" << _loader.getSchemaNamespace() - << R"cpp(::)cpp" << enumType.cppType << R"cpp( value, const ResolverParams&) + << R"cpp(::)cpp" << enumType.cppType << R"cpp( value, const ResolverParams&) { response::Value resolvedResult(response::Type::EnumValue); resolvedResult.set(std::string { s_names)cpp" - << enumType.cppType << R"cpp([static_cast(value)] }); + << enumType.cppType << R"cpp([static_cast(value)] }); return resolvedResult; }); @@ -1568,274 +1696,277 @@ service::AwaitableResolver Result<)cpp" template <> void Result<)cpp" << _loader.getSchemaNamespace() - << R"cpp(::)cpp" << enumType.cppType - << R"cpp(>::validateScalar(const response::Value& value) + << R"cpp(::)cpp" << enumType.cppType + << R"cpp(>::validateScalar(const response::Value& value) { if (!value.maybe_enum()) { throw service::schema_exception { { R"ex(not a valid )cpp" - << enumType.type << R"cpp( value)ex" } }; + << enumType.type << R"cpp( value)ex" } }; } const auto [itr, itrEnd] = internal::sorted_map_equal_range( - s_values)cpp" << enumType.cppType - << R"cpp(.begin(), - s_values)cpp" << enumType.cppType - << R"cpp(.end(), + s_values)cpp" + << enumType.cppType << R"cpp(.begin(), + s_values)cpp" + << enumType.cppType << R"cpp(.end(), std::string_view { value.get() }); if (itr == itrEnd) { throw service::schema_exception { { R"ex(not a valid )cpp" - << enumType.type << R"cpp( value)ex" } }; + << enumType.type << R"cpp( value)ex" } }; } } )cpp"; - } + } - for (const auto& inputType : _loader.getInputTypes()) - { - bool firstField = true; + for (const auto& inputType : _loader.getInputTypes()) + { + bool firstField = true; - sourceFile << R"cpp(template <> + sourceFile << R"cpp(template <> )cpp" << _loader.getSchemaNamespace() - << R"cpp(::)cpp" << inputType.cppType << R"cpp( Argument<)cpp" - << _loader.getSchemaNamespace() << R"cpp(::)cpp" << inputType.cppType - << R"cpp(>::convert(const response::Value& value) + << R"cpp(::)cpp" << inputType.cppType << R"cpp( Argument<)cpp" + << _loader.getSchemaNamespace() << R"cpp(::)cpp" << inputType.cppType + << R"cpp(>::convert(const response::Value& value) { )cpp"; - for (const auto& inputField : inputType.fields) + for (const auto& inputField : inputType.fields) + { + if (inputField.defaultValue.type() != response::Type::Null) { - if (inputField.defaultValue.type() != response::Type::Null) + if (firstField) { - if (firstField) - { - firstField = false; - sourceFile << R"cpp( const auto defaultValue = []() + firstField = false; + sourceFile << R"cpp( const auto defaultValue = []() { response::Value values(response::Type::Map); response::Value entry; )cpp"; - } + } - sourceFile << getArgumentDefaultValue(0, inputField.defaultValue) - << R"cpp( values.emplace_back(")cpp" << inputField.name - << R"cpp(", std::move(entry)); + sourceFile << getArgumentDefaultValue(0, inputField.defaultValue) + << R"cpp( values.emplace_back(")cpp" << inputField.name + << R"cpp(", std::move(entry)); )cpp"; - } } + } - if (!firstField) - { - sourceFile << R"cpp( + if (!firstField) + { + sourceFile << R"cpp( return values; }(); )cpp"; - } + } - for (const auto& inputField : inputType.fields) - { - sourceFile << getArgumentDeclaration(inputField, "value", "value", "defaultValue"); - } + for (const auto& inputField : inputType.fields) + { + sourceFile << getArgumentDeclaration(inputField, "value", "value", "defaultValue"); + } - if (!inputType.fields.empty()) - { - sourceFile << std::endl; - } + if (!inputType.fields.empty()) + { + sourceFile << std::endl; + } - sourceFile << R"cpp( return )cpp" << _loader.getSchemaNamespace() << R"cpp(::)cpp" - << inputType.cppType << R"cpp( { + sourceFile << R"cpp( return )cpp" << _loader.getSchemaNamespace() << R"cpp(::)cpp" + << inputType.cppType << R"cpp( { )cpp"; - firstField = true; + firstField = true; - for (const auto& inputField : inputType.fields) - { - std::string fieldName(inputField.cppName); + for (const auto& inputField : inputType.fields) + { + std::string fieldName(inputField.cppName); - if (!firstField) - { - sourceFile << R"cpp(, + if (!firstField) + { + sourceFile << R"cpp(, )cpp"; - } + } - const bool shouldMove = SchemaLoader::shouldMoveInputField(inputField); + const bool shouldMove = SchemaLoader::shouldMoveInputField(inputField); - firstField = false; - fieldName[0] = - static_cast(std::toupper(static_cast(fieldName[0]))); + firstField = false; + fieldName[0] = + static_cast(std::toupper(static_cast(fieldName[0]))); - sourceFile << R"cpp( )cpp"; + sourceFile << R"cpp( )cpp"; - if (shouldMove) - { - sourceFile << R"cpp(std::move()cpp"; - } + if (shouldMove) + { + sourceFile << R"cpp(std::move()cpp"; + } - sourceFile << R"cpp(value)cpp" << fieldName; + sourceFile << R"cpp(value)cpp" << fieldName; - if (shouldMove) - { - sourceFile << R"cpp())cpp"; - } + if (shouldMove) + { + sourceFile << R"cpp())cpp"; } + } - sourceFile << R"cpp( + sourceFile << R"cpp( }; } )cpp"; - } - - serviceNamespace.exit(); - sourceFile << std::endl; } - NamespaceScope schemaNamespace { sourceFile, _loader.getSchemaNamespace() }; + serviceNamespace.exit(); + pendingSeparator.add(); - for (const auto& inputType : _loader.getInputTypes()) + if (!_loader.getInputTypes().empty()) { - sourceFile << std::endl - << inputType.cppType << R"cpp(::)cpp" << inputType.cppType - << R"cpp(() noexcept)cpp"; + pendingSeparator.reset(); - bool firstField = true; + NamespaceScope schemaNamespace { sourceFile, _loader.getSchemaNamespace() }; - for (const auto& inputField : inputType.fields) + for (const auto& inputType : _loader.getInputTypes()) { - sourceFile << R"cpp( + sourceFile << std::endl + << inputType.cppType << R"cpp(::)cpp" << inputType.cppType + << R"cpp(() noexcept)cpp"; + + bool firstField = true; + + for (const auto& inputField : inputType.fields) + { + sourceFile << R"cpp( )cpp" << (firstField ? R"cpp(:)cpp" : R"cpp(,)cpp") - << R"cpp( )cpp" << inputField.cppName << R"cpp( {})cpp"; - firstField = false; - } + << R"cpp( )cpp" << inputField.cppName << R"cpp( {})cpp"; + firstField = false; + } - sourceFile << R"cpp( + sourceFile << R"cpp( { // Explicit definition to prevent ODR violations when LTO is enabled. } )cpp" << inputType.cppType - << R"cpp(::)cpp" << inputType.cppType << R"cpp(()cpp"; + << R"cpp(::)cpp" << inputType.cppType << R"cpp(()cpp"; - firstField = true; + firstField = true; - for (const auto& inputField : inputType.fields) - { - if (!firstField) + for (const auto& inputField : inputType.fields) { - sourceFile << R"cpp(,)cpp"; - } + if (!firstField) + { + sourceFile << R"cpp(,)cpp"; + } - firstField = false; - sourceFile << R"cpp( + firstField = false; + sourceFile << R"cpp( )cpp" << _loader.getInputCppType(inputField) - << R"cpp( )cpp" << inputField.cppName << R"cpp(Arg)cpp"; - } + << R"cpp( )cpp" << inputField.cppName << R"cpp(Arg)cpp"; + } - sourceFile << R"cpp() noexcept + sourceFile << R"cpp() noexcept )cpp"; - firstField = true; + firstField = true; - for (const auto& inputField : inputType.fields) - { - sourceFile << (firstField ? R"cpp( : )cpp" : R"cpp( , )cpp"); - firstField = false; + for (const auto& inputField : inputType.fields) + { + sourceFile << (firstField ? R"cpp( : )cpp" : R"cpp( , )cpp"); + firstField = false; - sourceFile << inputField.cppName << R"cpp( { std::move()cpp" << inputField.cppName - << R"cpp(Arg) } + sourceFile << inputField.cppName << R"cpp( { std::move()cpp" << inputField.cppName + << R"cpp(Arg) } )cpp"; - } + } - sourceFile << R"cpp({ + sourceFile << R"cpp({ } )cpp" << inputType.cppType - << R"cpp(::)cpp" << inputType.cppType << R"cpp((const )cpp" << inputType.cppType - << R"cpp(& other) + << R"cpp(::)cpp" << inputType.cppType << R"cpp((const )cpp" + << inputType.cppType << R"cpp(& other) )cpp"; - firstField = true; - - for (const auto& inputField : inputType.fields) - { - sourceFile << (firstField ? R"cpp( : )cpp" : R"cpp( , )cpp"); - firstField = false; - - sourceFile << inputField.cppName << R"cpp( { service::ModifiedArgument<)cpp" - << _loader.getCppType(inputField.type) << R"cpp(>::duplicate)cpp"; + firstField = true; - if (!inputField.modifiers.empty()) + for (const auto& inputField : inputType.fields) { - bool firstModifier = true; + sourceFile << (firstField ? R"cpp( : )cpp" : R"cpp( , )cpp"); + firstField = false; + + sourceFile << inputField.cppName << R"cpp( { service::ModifiedArgument<)cpp" + << _loader.getCppType(inputField.type) << R"cpp(>::duplicate)cpp"; - for (const auto modifier : inputField.modifiers) + if (!inputField.modifiers.empty()) { - sourceFile << (firstModifier ? R"cpp(<)cpp" : R"cpp(, )cpp"); - firstModifier = false; + bool firstModifier = true; - switch (modifier) + for (const auto modifier : inputField.modifiers) { - case service::TypeModifier::None: - sourceFile << R"cpp(service::TypeModifier::None)cpp"; - break; + sourceFile << (firstModifier ? R"cpp(<)cpp" : R"cpp(, )cpp"); + firstModifier = false; + + switch (modifier) + { + case service::TypeModifier::None: + sourceFile << R"cpp(service::TypeModifier::None)cpp"; + break; - case service::TypeModifier::Nullable: - sourceFile << R"cpp(service::TypeModifier::Nullable)cpp"; - break; + case service::TypeModifier::Nullable: + sourceFile << R"cpp(service::TypeModifier::Nullable)cpp"; + break; - case service::TypeModifier::List: - sourceFile << R"cpp(service::TypeModifier::List)cpp"; - break; + case service::TypeModifier::List: + sourceFile << R"cpp(service::TypeModifier::List)cpp"; + break; + } } - } - sourceFile << R"cpp(>)cpp"; - } + sourceFile << R"cpp(>)cpp"; + } - sourceFile << R"cpp((other.)cpp" << inputField.cppName << R"cpp() } + sourceFile << R"cpp((other.)cpp" << inputField.cppName << R"cpp() } )cpp"; - } + } - sourceFile << R"cpp({ + sourceFile << R"cpp({ } )cpp" << inputType.cppType - << R"cpp(::)cpp" << inputType.cppType << R"cpp(()cpp" << inputType.cppType - << R"cpp(&& other) noexcept + << R"cpp(::)cpp" << inputType.cppType << R"cpp(()cpp" << inputType.cppType + << R"cpp(&& other) noexcept )cpp"; - firstField = true; + firstField = true; - for (const auto& inputField : inputType.fields) - { - sourceFile << (firstField ? R"cpp( : )cpp" : R"cpp( , )cpp"); - firstField = false; + for (const auto& inputField : inputType.fields) + { + sourceFile << (firstField ? R"cpp( : )cpp" : R"cpp( , )cpp"); + firstField = false; - sourceFile << inputField.cppName << R"cpp( { std::move(other.)cpp" << inputField.cppName - << R"cpp() } + sourceFile << inputField.cppName << R"cpp( { std::move(other.)cpp" + << inputField.cppName << R"cpp() } )cpp"; - } + } - sourceFile << R"cpp({ + sourceFile << R"cpp({ } )cpp" << inputType.cppType - << R"cpp(::~)cpp" << inputType.cppType << R"cpp(() + << R"cpp(::~)cpp" << inputType.cppType << R"cpp(() { // Explicit definition to prevent ODR violations when LTO is enabled. } )cpp" << inputType.cppType - << R"cpp(& )cpp" << inputType.cppType << R"cpp(::operator=(const )cpp" - << inputType.cppType << R"cpp(& other) + << R"cpp(& )cpp" << inputType.cppType << R"cpp(::operator=(const )cpp" + << inputType.cppType << R"cpp(& other) { )cpp" << inputType.cppType - << R"cpp( value { other }; + << R"cpp( value { other }; std::swap(*this, value); @@ -1843,24 +1974,90 @@ void Result<)cpp" << _loader.getSchemaNamespace() } )cpp" << inputType.cppType - << R"cpp(& )cpp" << inputType.cppType << R"cpp(::operator=()cpp" - << inputType.cppType << R"cpp(&& other) noexcept + << R"cpp(& )cpp" << inputType.cppType << R"cpp(::operator=()cpp" + << inputType.cppType << R"cpp(&& other) noexcept { )cpp"; - for (const auto& inputField : inputType.fields) - { - sourceFile << R"cpp( )cpp" << inputField.cppName << R"cpp( = std::move(other.)cpp" - << inputField.cppName << R"cpp(); + for (const auto& inputField : inputType.fields) + { + sourceFile << R"cpp( )cpp" << inputField.cppName + << R"cpp( = std::move(other.)cpp" << inputField.cppName << R"cpp(); )cpp"; - } + } - sourceFile << R"cpp( + sourceFile << R"cpp( return *this; } + +)cpp"; + } + } + + return true; +} + +bool Generator::outputSchemaSource() const noexcept +{ + std::ofstream sourceFile(_schemaSourcePath, std::ios_base::trunc); + + sourceFile << R"cpp(// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// WARNING! Do not edit this file manually, your changes will be overwritten. + +)cpp"; + + if (!_loader.isIntrospection()) + { + if (_loader.getOperationTypes().empty()) + { + // Normally this would be included by each of the operation object headers. + sourceFile << R"cpp(#include ")cpp" << getSchemaHeaderPath() << R"cpp(" +)cpp"; + } + else + { + for (const auto& operation : _loader.getOperationTypes()) + { + sourceFile << R"cpp(#include ")cpp" << operation.cppType << R"cpp(Object.h" +)cpp"; + } + } + + sourceFile << std::endl; + } + + if (_loader.isIntrospection()) + { + sourceFile << R"cpp(#include "graphqlservice/internal/Introspection.h" +)cpp"; + } + else + { + sourceFile << R"cpp(#include "graphqlservice/internal/Schema.h" + +#include "graphqlservice/introspection/IntrospectionSchema.h" )cpp"; } + sourceFile << R"cpp( +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std::literals; + +)cpp"; + + const auto schemaNamespace = std::format(R"cpp(graphql::{})cpp", _loader.getSchemaNamespace()); + NamespaceScope schemaNamespaceScope { sourceFile, schemaNamespace }; + if (!_loader.isIntrospection()) { bool firstOperation = true; @@ -2094,7 +2291,10 @@ Operations::Operations()cpp"; { bool firstValue = true; - sourceFile << R"cpp( type)cpp" << enumType.cppType << R"cpp(->AddEnumValues({ + sourceFile << R"cpp( static const auto s_names)cpp" << enumType.cppType + << R"cpp( = get)cpp" << enumType.cppType << R"cpp(Names(); + type)cpp" << enumType.cppType + << R"cpp(->AddEnumValues({ )cpp"; for (const auto& enumValue : enumType.values) @@ -2106,7 +2306,7 @@ Operations::Operations()cpp"; } firstValue = false; - sourceFile << R"cpp( { service::s_names)cpp" << enumType.cppType + sourceFile << R"cpp( { s_names)cpp" << enumType.cppType << R"cpp([static_cast()cpp" << _loader.getSchemaNamespace() << R"cpp(::)cpp" << enumType.cppType << R"cpp(::)cpp" << enumValue.cppValue << R"cpp()], R"md()cpp"; @@ -2292,7 +2492,8 @@ Operations::Operations()cpp"; )cpp"; } sourceFile << R"cpp(}, )cpp" - << (directive.isRepeatable ? R"cpp(true)cpp" : R"cpp(false)cpp") << R"cpp()); + << (directive.isRepeatable ? R"cpp(true)cpp" : R"cpp(false)cpp") + << R"cpp()); )cpp"; } } @@ -3224,7 +3425,7 @@ std::vector Generator::outputSeparateFiles() const noexcept IncludeGuardScope includeGuard { headerFile, headerFilename }; headerFile << R"cpp(#include ")cpp" - << std::filesystem::path(_headerPath).filename().string() << R"cpp(" + << std::filesystem::path(_schemaHeaderPath).filename().string() << R"cpp(" )cpp"; @@ -3308,7 +3509,7 @@ using namespace std::literals; IncludeGuardScope includeGuard { headerFile, headerFilename }; headerFile << R"cpp(#include ")cpp" - << std::filesystem::path(_headerPath).filename().string() << R"cpp(" + << std::filesystem::path(_schemaHeaderPath).filename().string() << R"cpp(" )cpp"; @@ -3412,7 +3613,7 @@ using namespace std::literals; IncludeGuardScope includeGuard { headerFile, headerFilename }; headerFile << R"cpp(#include ")cpp" - << std::filesystem::path(_headerPath).filename().string() << R"cpp(" + << std::filesystem::path(_schemaHeaderPath).filename().string() << R"cpp(" )cpp"; diff --git a/src/introspection/IntrospectionSchema.cpp b/src/introspection/IntrospectionSchema.cpp index f735c21d..5bc857ed 100644 --- a/src/introspection/IntrospectionSchema.cpp +++ b/src/introspection/IntrospectionSchema.cpp @@ -16,124 +16,7 @@ using namespace std::literals; -namespace graphql { -namespace service { - -static const auto s_namesTypeKind = introspection::getTypeKindNames(); -static const auto s_valuesTypeKind = introspection::getTypeKindValues(); - -template <> -introspection::TypeKind Argument::convert(const response::Value& value) -{ - if (!value.maybe_enum()) - { - throw service::schema_exception { { R"ex(not a valid __TypeKind value)ex" } }; - } - - const auto result = internal::sorted_map_lookup( - s_valuesTypeKind, - std::string_view { value.get() }); - - if (!result) - { - throw service::schema_exception { { R"ex(not a valid __TypeKind value)ex" } }; - } - - return *result; -} - -template <> -service::AwaitableResolver Result::convert(service::AwaitableScalar result, ResolverParams&& params) -{ - return ModifiedResult::resolve(std::move(result), std::move(params), - [](introspection::TypeKind value, const ResolverParams&) - { - response::Value resolvedResult(response::Type::EnumValue); - - resolvedResult.set(std::string { s_namesTypeKind[static_cast(value)] }); - - return resolvedResult; - }); -} - -template <> -void Result::validateScalar(const response::Value& value) -{ - if (!value.maybe_enum()) - { - throw service::schema_exception { { R"ex(not a valid __TypeKind value)ex" } }; - } - - const auto [itr, itrEnd] = internal::sorted_map_equal_range( - s_valuesTypeKind.begin(), - s_valuesTypeKind.end(), - std::string_view { value.get() }); - - if (itr == itrEnd) - { - throw service::schema_exception { { R"ex(not a valid __TypeKind value)ex" } }; - } -} - -static const auto s_namesDirectiveLocation = introspection::getDirectiveLocationNames(); -static const auto s_valuesDirectiveLocation = introspection::getDirectiveLocationValues(); - -template <> -introspection::DirectiveLocation Argument::convert(const response::Value& value) -{ - if (!value.maybe_enum()) - { - throw service::schema_exception { { R"ex(not a valid __DirectiveLocation value)ex" } }; - } - - const auto result = internal::sorted_map_lookup( - s_valuesDirectiveLocation, - std::string_view { value.get() }); - - if (!result) - { - throw service::schema_exception { { R"ex(not a valid __DirectiveLocation value)ex" } }; - } - - return *result; -} - -template <> -service::AwaitableResolver Result::convert(service::AwaitableScalar result, ResolverParams&& params) -{ - return ModifiedResult::resolve(std::move(result), std::move(params), - [](introspection::DirectiveLocation value, const ResolverParams&) - { - response::Value resolvedResult(response::Type::EnumValue); - - resolvedResult.set(std::string { s_namesDirectiveLocation[static_cast(value)] }); - - return resolvedResult; - }); -} - -template <> -void Result::validateScalar(const response::Value& value) -{ - if (!value.maybe_enum()) - { - throw service::schema_exception { { R"ex(not a valid __DirectiveLocation value)ex" } }; - } - - const auto [itr, itrEnd] = internal::sorted_map_equal_range( - s_valuesDirectiveLocation.begin(), - s_valuesDirectiveLocation.end(), - std::string_view { value.get() }); - - if (itr == itrEnd) - { - throw service::schema_exception { { R"ex(not a valid __DirectiveLocation value)ex" } }; - } -} - -} // namespace service - -namespace introspection { +namespace graphql::introspection { void AddTypesToSchema(const std::shared_ptr& schema) { @@ -159,36 +42,38 @@ void AddTypesToSchema(const std::shared_ptr& schema) auto typeDirective = schema::ObjectType::Make(R"gql(__Directive)gql"sv, R"md()md"sv); schema->AddType(R"gql(__Directive)gql"sv, typeDirective); + static const auto s_namesTypeKind = getTypeKindNames(); typeTypeKind->AddEnumValues({ - { service::s_namesTypeKind[static_cast(introspection::TypeKind::SCALAR)], R"md()md"sv, std::nullopt }, - { service::s_namesTypeKind[static_cast(introspection::TypeKind::OBJECT)], R"md()md"sv, std::nullopt }, - { service::s_namesTypeKind[static_cast(introspection::TypeKind::INTERFACE)], R"md()md"sv, std::nullopt }, - { service::s_namesTypeKind[static_cast(introspection::TypeKind::UNION)], R"md()md"sv, std::nullopt }, - { service::s_namesTypeKind[static_cast(introspection::TypeKind::ENUM)], R"md()md"sv, std::nullopt }, - { service::s_namesTypeKind[static_cast(introspection::TypeKind::INPUT_OBJECT)], R"md()md"sv, std::nullopt }, - { service::s_namesTypeKind[static_cast(introspection::TypeKind::LIST)], R"md()md"sv, std::nullopt }, - { service::s_namesTypeKind[static_cast(introspection::TypeKind::NON_NULL)], R"md()md"sv, std::nullopt } + { s_namesTypeKind[static_cast(introspection::TypeKind::SCALAR)], R"md()md"sv, std::nullopt }, + { s_namesTypeKind[static_cast(introspection::TypeKind::OBJECT)], R"md()md"sv, std::nullopt }, + { s_namesTypeKind[static_cast(introspection::TypeKind::INTERFACE)], R"md()md"sv, std::nullopt }, + { s_namesTypeKind[static_cast(introspection::TypeKind::UNION)], R"md()md"sv, std::nullopt }, + { s_namesTypeKind[static_cast(introspection::TypeKind::ENUM)], R"md()md"sv, std::nullopt }, + { s_namesTypeKind[static_cast(introspection::TypeKind::INPUT_OBJECT)], R"md()md"sv, std::nullopt }, + { s_namesTypeKind[static_cast(introspection::TypeKind::LIST)], R"md()md"sv, std::nullopt }, + { s_namesTypeKind[static_cast(introspection::TypeKind::NON_NULL)], R"md()md"sv, std::nullopt } }); + static const auto s_namesDirectiveLocation = getDirectiveLocationNames(); typeDirectiveLocation->AddEnumValues({ - { service::s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::QUERY)], R"md()md"sv, std::nullopt }, - { service::s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::MUTATION)], R"md()md"sv, std::nullopt }, - { service::s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::SUBSCRIPTION)], R"md()md"sv, std::nullopt }, - { service::s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::FIELD)], R"md()md"sv, std::nullopt }, - { service::s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::FRAGMENT_DEFINITION)], R"md()md"sv, std::nullopt }, - { service::s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::FRAGMENT_SPREAD)], R"md()md"sv, std::nullopt }, - { service::s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::INLINE_FRAGMENT)], R"md()md"sv, std::nullopt }, - { service::s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::VARIABLE_DEFINITION)], R"md()md"sv, std::nullopt }, - { service::s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::SCHEMA)], R"md()md"sv, std::nullopt }, - { service::s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::SCALAR)], R"md()md"sv, std::nullopt }, - { service::s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::OBJECT)], R"md()md"sv, std::nullopt }, - { service::s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::FIELD_DEFINITION)], R"md()md"sv, std::nullopt }, - { service::s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::ARGUMENT_DEFINITION)], R"md()md"sv, std::nullopt }, - { service::s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::INTERFACE)], R"md()md"sv, std::nullopt }, - { service::s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::UNION)], R"md()md"sv, std::nullopt }, - { service::s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::ENUM)], R"md()md"sv, std::nullopt }, - { service::s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::ENUM_VALUE)], R"md()md"sv, std::nullopt }, - { service::s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::INPUT_OBJECT)], R"md()md"sv, std::nullopt }, - { service::s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::INPUT_FIELD_DEFINITION)], R"md()md"sv, std::nullopt } + { s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::QUERY)], R"md()md"sv, std::nullopt }, + { s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::MUTATION)], R"md()md"sv, std::nullopt }, + { s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::SUBSCRIPTION)], R"md()md"sv, std::nullopt }, + { s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::FIELD)], R"md()md"sv, std::nullopt }, + { s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::FRAGMENT_DEFINITION)], R"md()md"sv, std::nullopt }, + { s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::FRAGMENT_SPREAD)], R"md()md"sv, std::nullopt }, + { s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::INLINE_FRAGMENT)], R"md()md"sv, std::nullopt }, + { s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::VARIABLE_DEFINITION)], R"md()md"sv, std::nullopt }, + { s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::SCHEMA)], R"md()md"sv, std::nullopt }, + { s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::SCALAR)], R"md()md"sv, std::nullopt }, + { s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::OBJECT)], R"md()md"sv, std::nullopt }, + { s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::FIELD_DEFINITION)], R"md()md"sv, std::nullopt }, + { s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::ARGUMENT_DEFINITION)], R"md()md"sv, std::nullopt }, + { s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::INTERFACE)], R"md()md"sv, std::nullopt }, + { s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::UNION)], R"md()md"sv, std::nullopt }, + { s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::ENUM)], R"md()md"sv, std::nullopt }, + { s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::ENUM_VALUE)], R"md()md"sv, std::nullopt }, + { s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::INPUT_OBJECT)], R"md()md"sv, std::nullopt }, + { s_namesDirectiveLocation[static_cast(introspection::DirectiveLocation::INPUT_FIELD_DEFINITION)], R"md()md"sv, std::nullopt } }); AddSchemaDetails(typeSchema, schema); @@ -225,5 +110,4 @@ void AddTypesToSchema(const std::shared_ptr& schema) }, false)); } -} // namespace introspection -} // namespace graphql +} // namespace graphql::introspection diff --git a/src/introspection/IntrospectionSchema.h b/src/introspection/IntrospectionSchema.h index b754e4ad..b39fe13f 100644 --- a/src/introspection/IntrospectionSchema.h +++ b/src/introspection/IntrospectionSchema.h @@ -11,9 +11,12 @@ #include "graphqlservice/GraphQLResponse.h" #include "graphqlservice/GraphQLService.h" +#include "graphqlservice/internal/DllExports.h" #include "graphqlservice/internal/Version.h" #include "graphqlservice/internal/Schema.h" +#include "IntrospectionSharedTypes.h" + #include #include #include @@ -23,130 +26,7 @@ static_assert(graphql::internal::MajorVersion == 5, "regenerate with schemagen: major version mismatch"); static_assert(graphql::internal::MinorVersion == 0, "regenerate with schemagen: minor version mismatch"); -namespace graphql { -namespace introspection { - -enum class TypeKind -{ - SCALAR, - OBJECT, - INTERFACE, - UNION, - ENUM, - INPUT_OBJECT, - LIST, - NON_NULL -}; - -[[nodiscard("unnecessary call")]] constexpr auto getTypeKindNames() noexcept -{ - using namespace std::literals; - - return std::array { - R"gql(SCALAR)gql"sv, - R"gql(OBJECT)gql"sv, - R"gql(INTERFACE)gql"sv, - R"gql(UNION)gql"sv, - R"gql(ENUM)gql"sv, - R"gql(INPUT_OBJECT)gql"sv, - R"gql(LIST)gql"sv, - R"gql(NON_NULL)gql"sv - }; -} - -[[nodiscard("unnecessary call")]] constexpr auto getTypeKindValues() noexcept -{ - using namespace std::literals; - - return std::array, 8> { - std::make_pair(R"gql(ENUM)gql"sv, TypeKind::ENUM), - std::make_pair(R"gql(LIST)gql"sv, TypeKind::LIST), - std::make_pair(R"gql(UNION)gql"sv, TypeKind::UNION), - std::make_pair(R"gql(OBJECT)gql"sv, TypeKind::OBJECT), - std::make_pair(R"gql(SCALAR)gql"sv, TypeKind::SCALAR), - std::make_pair(R"gql(NON_NULL)gql"sv, TypeKind::NON_NULL), - std::make_pair(R"gql(INTERFACE)gql"sv, TypeKind::INTERFACE), - std::make_pair(R"gql(INPUT_OBJECT)gql"sv, TypeKind::INPUT_OBJECT) - }; -} - -enum class DirectiveLocation -{ - QUERY, - MUTATION, - SUBSCRIPTION, - FIELD, - FRAGMENT_DEFINITION, - FRAGMENT_SPREAD, - INLINE_FRAGMENT, - VARIABLE_DEFINITION, - SCHEMA, - SCALAR, - OBJECT, - FIELD_DEFINITION, - ARGUMENT_DEFINITION, - INTERFACE, - UNION, - ENUM, - ENUM_VALUE, - INPUT_OBJECT, - INPUT_FIELD_DEFINITION -}; - -[[nodiscard("unnecessary call")]] constexpr auto getDirectiveLocationNames() noexcept -{ - using namespace std::literals; - - return std::array { - R"gql(QUERY)gql"sv, - R"gql(MUTATION)gql"sv, - R"gql(SUBSCRIPTION)gql"sv, - R"gql(FIELD)gql"sv, - R"gql(FRAGMENT_DEFINITION)gql"sv, - R"gql(FRAGMENT_SPREAD)gql"sv, - R"gql(INLINE_FRAGMENT)gql"sv, - R"gql(VARIABLE_DEFINITION)gql"sv, - R"gql(SCHEMA)gql"sv, - R"gql(SCALAR)gql"sv, - R"gql(OBJECT)gql"sv, - R"gql(FIELD_DEFINITION)gql"sv, - R"gql(ARGUMENT_DEFINITION)gql"sv, - R"gql(INTERFACE)gql"sv, - R"gql(UNION)gql"sv, - R"gql(ENUM)gql"sv, - R"gql(ENUM_VALUE)gql"sv, - R"gql(INPUT_OBJECT)gql"sv, - R"gql(INPUT_FIELD_DEFINITION)gql"sv - }; -} - -[[nodiscard("unnecessary call")]] constexpr auto getDirectiveLocationValues() noexcept -{ - using namespace std::literals; - - return std::array, 19> { - std::make_pair(R"gql(ENUM)gql"sv, DirectiveLocation::ENUM), - std::make_pair(R"gql(FIELD)gql"sv, DirectiveLocation::FIELD), - std::make_pair(R"gql(QUERY)gql"sv, DirectiveLocation::QUERY), - std::make_pair(R"gql(UNION)gql"sv, DirectiveLocation::UNION), - std::make_pair(R"gql(OBJECT)gql"sv, DirectiveLocation::OBJECT), - std::make_pair(R"gql(SCALAR)gql"sv, DirectiveLocation::SCALAR), - std::make_pair(R"gql(SCHEMA)gql"sv, DirectiveLocation::SCHEMA), - std::make_pair(R"gql(MUTATION)gql"sv, DirectiveLocation::MUTATION), - std::make_pair(R"gql(INTERFACE)gql"sv, DirectiveLocation::INTERFACE), - std::make_pair(R"gql(ENUM_VALUE)gql"sv, DirectiveLocation::ENUM_VALUE), - std::make_pair(R"gql(INPUT_OBJECT)gql"sv, DirectiveLocation::INPUT_OBJECT), - std::make_pair(R"gql(SUBSCRIPTION)gql"sv, DirectiveLocation::SUBSCRIPTION), - std::make_pair(R"gql(FRAGMENT_SPREAD)gql"sv, DirectiveLocation::FRAGMENT_SPREAD), - std::make_pair(R"gql(INLINE_FRAGMENT)gql"sv, DirectiveLocation::INLINE_FRAGMENT), - std::make_pair(R"gql(FIELD_DEFINITION)gql"sv, DirectiveLocation::FIELD_DEFINITION), - std::make_pair(R"gql(ARGUMENT_DEFINITION)gql"sv, DirectiveLocation::ARGUMENT_DEFINITION), - std::make_pair(R"gql(FRAGMENT_DEFINITION)gql"sv, DirectiveLocation::FRAGMENT_DEFINITION), - std::make_pair(R"gql(VARIABLE_DEFINITION)gql"sv, DirectiveLocation::VARIABLE_DEFINITION), - std::make_pair(R"gql(INPUT_FIELD_DEFINITION)gql"sv, DirectiveLocation::INPUT_FIELD_DEFINITION) - }; -} - +namespace graphql::introspection { class Schema; class Type; class Field; @@ -174,33 +54,6 @@ void AddDirectiveDetails(const std::shared_ptr& typeDirectiv GRAPHQLSERVICE_EXPORT void AddTypesToSchema(const std::shared_ptr& schema); -} // namespace introspection - -namespace service { - -#ifdef GRAPHQL_DLLEXPORTS -// Export all of the built-in converters -template <> -GRAPHQLSERVICE_EXPORT introspection::TypeKind Argument::convert( - const response::Value& value); -template <> -GRAPHQLSERVICE_EXPORT AwaitableResolver Result::convert( - AwaitableScalar result, ResolverParams&& params); -template <> -GRAPHQLSERVICE_EXPORT void Result::validateScalar( - const response::Value& value); -template <> -GRAPHQLSERVICE_EXPORT introspection::DirectiveLocation Argument::convert( - const response::Value& value); -template <> -GRAPHQLSERVICE_EXPORT AwaitableResolver Result::convert( - AwaitableScalar result, ResolverParams&& params); -template <> -GRAPHQLSERVICE_EXPORT void Result::validateScalar( - const response::Value& value); -#endif // GRAPHQL_DLLEXPORTS - -} // namespace service -} // namespace graphql +} // namespace graphql::introspection #endif // INTROSPECTIONSCHEMA_H diff --git a/src/introspection/IntrospectionSchema.ixx b/src/introspection/IntrospectionSchema.ixx index 45f3f14a..8ce51120 100644 --- a/src/introspection/IntrospectionSchema.ixx +++ b/src/introspection/IntrospectionSchema.ixx @@ -9,6 +9,8 @@ module; export module GraphQL.Introspection.IntrospectionSchema; +export import GraphQL.Introspection.IntrospectionSharedTypes; + export import GraphQL.Introspection.SchemaObject; export import GraphQL.Introspection.TypeObject; export import GraphQL.Introspection.FieldObject; @@ -18,14 +20,6 @@ export import GraphQL.Introspection.DirectiveObject; export namespace graphql::introspection { -using introspection::TypeKind; -using introspection::getTypeKindNames; -using introspection::getTypeKindValues; - -using introspection::DirectiveLocation; -using introspection::getDirectiveLocationNames; -using introspection::getDirectiveLocationValues; - using introspection::AddSchemaDetails; using introspection::AddTypeDetails; using introspection::AddFieldDetails; diff --git a/src/introspection/IntrospectionSharedTypes.cpp b/src/introspection/IntrospectionSharedTypes.cpp new file mode 100644 index 00000000..5b1892fe --- /dev/null +++ b/src/introspection/IntrospectionSharedTypes.cpp @@ -0,0 +1,137 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// WARNING! Do not edit this file manually, your changes will be overwritten. + +#include "graphqlservice/GraphQLService.h" + +#include "IntrospectionSharedTypes.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std::literals; + +namespace graphql { +namespace service { + +static const auto s_namesTypeKind = introspection::getTypeKindNames(); +static const auto s_valuesTypeKind = introspection::getTypeKindValues(); + +template <> +introspection::TypeKind Argument::convert(const response::Value& value) +{ + if (!value.maybe_enum()) + { + throw service::schema_exception { { R"ex(not a valid __TypeKind value)ex" } }; + } + + const auto result = internal::sorted_map_lookup( + s_valuesTypeKind, + std::string_view { value.get() }); + + if (!result) + { + throw service::schema_exception { { R"ex(not a valid __TypeKind value)ex" } }; + } + + return *result; +} + +template <> +service::AwaitableResolver Result::convert(service::AwaitableScalar result, ResolverParams&& params) +{ + return ModifiedResult::resolve(std::move(result), std::move(params), + [](introspection::TypeKind value, const ResolverParams&) + { + response::Value resolvedResult(response::Type::EnumValue); + + resolvedResult.set(std::string { s_namesTypeKind[static_cast(value)] }); + + return resolvedResult; + }); +} + +template <> +void Result::validateScalar(const response::Value& value) +{ + if (!value.maybe_enum()) + { + throw service::schema_exception { { R"ex(not a valid __TypeKind value)ex" } }; + } + + const auto [itr, itrEnd] = internal::sorted_map_equal_range( + s_valuesTypeKind.begin(), + s_valuesTypeKind.end(), + std::string_view { value.get() }); + + if (itr == itrEnd) + { + throw service::schema_exception { { R"ex(not a valid __TypeKind value)ex" } }; + } +} + +static const auto s_namesDirectiveLocation = introspection::getDirectiveLocationNames(); +static const auto s_valuesDirectiveLocation = introspection::getDirectiveLocationValues(); + +template <> +introspection::DirectiveLocation Argument::convert(const response::Value& value) +{ + if (!value.maybe_enum()) + { + throw service::schema_exception { { R"ex(not a valid __DirectiveLocation value)ex" } }; + } + + const auto result = internal::sorted_map_lookup( + s_valuesDirectiveLocation, + std::string_view { value.get() }); + + if (!result) + { + throw service::schema_exception { { R"ex(not a valid __DirectiveLocation value)ex" } }; + } + + return *result; +} + +template <> +service::AwaitableResolver Result::convert(service::AwaitableScalar result, ResolverParams&& params) +{ + return ModifiedResult::resolve(std::move(result), std::move(params), + [](introspection::DirectiveLocation value, const ResolverParams&) + { + response::Value resolvedResult(response::Type::EnumValue); + + resolvedResult.set(std::string { s_namesDirectiveLocation[static_cast(value)] }); + + return resolvedResult; + }); +} + +template <> +void Result::validateScalar(const response::Value& value) +{ + if (!value.maybe_enum()) + { + throw service::schema_exception { { R"ex(not a valid __DirectiveLocation value)ex" } }; + } + + const auto [itr, itrEnd] = internal::sorted_map_equal_range( + s_valuesDirectiveLocation.begin(), + s_valuesDirectiveLocation.end(), + std::string_view { value.get() }); + + if (itr == itrEnd) + { + throw service::schema_exception { { R"ex(not a valid __DirectiveLocation value)ex" } }; + } +} + +} // namespace service +} // namespace graphql diff --git a/src/introspection/IntrospectionSharedTypes.h b/src/introspection/IntrospectionSharedTypes.h new file mode 100644 index 00000000..9e1d5acb --- /dev/null +++ b/src/introspection/IntrospectionSharedTypes.h @@ -0,0 +1,180 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// WARNING! Do not edit this file manually, your changes will be overwritten. + +#pragma once + +#ifndef INTROSPECTIONSHAREDTYPES_H +#define INTROSPECTIONSHAREDTYPES_H + +#include "graphqlservice/GraphQLResponse.h" + +#include "graphqlservice/internal/DllExports.h" +#include "graphqlservice/internal/Version.h" + +#include +#include +#include +#include +#include +#include + +// Check if the library version is compatible with schemagen 5.0.0 +static_assert(graphql::internal::MajorVersion == 5, "regenerate with schemagen: major version mismatch"); +static_assert(graphql::internal::MinorVersion == 0, "regenerate with schemagen: minor version mismatch"); + +namespace graphql { +namespace introspection { + +enum class TypeKind +{ + SCALAR, + OBJECT, + INTERFACE, + UNION, + ENUM, + INPUT_OBJECT, + LIST, + NON_NULL +}; + +[[nodiscard("unnecessary call")]] constexpr auto getTypeKindNames() noexcept +{ + using namespace std::literals; + + return std::array { + R"gql(SCALAR)gql"sv, + R"gql(OBJECT)gql"sv, + R"gql(INTERFACE)gql"sv, + R"gql(UNION)gql"sv, + R"gql(ENUM)gql"sv, + R"gql(INPUT_OBJECT)gql"sv, + R"gql(LIST)gql"sv, + R"gql(NON_NULL)gql"sv + }; +} + +[[nodiscard("unnecessary call")]] constexpr auto getTypeKindValues() noexcept +{ + using namespace std::literals; + + return std::array, 8> { + std::make_pair(R"gql(ENUM)gql"sv, TypeKind::ENUM), + std::make_pair(R"gql(LIST)gql"sv, TypeKind::LIST), + std::make_pair(R"gql(UNION)gql"sv, TypeKind::UNION), + std::make_pair(R"gql(OBJECT)gql"sv, TypeKind::OBJECT), + std::make_pair(R"gql(SCALAR)gql"sv, TypeKind::SCALAR), + std::make_pair(R"gql(NON_NULL)gql"sv, TypeKind::NON_NULL), + std::make_pair(R"gql(INTERFACE)gql"sv, TypeKind::INTERFACE), + std::make_pair(R"gql(INPUT_OBJECT)gql"sv, TypeKind::INPUT_OBJECT) + }; +} + +enum class DirectiveLocation +{ + QUERY, + MUTATION, + SUBSCRIPTION, + FIELD, + FRAGMENT_DEFINITION, + FRAGMENT_SPREAD, + INLINE_FRAGMENT, + VARIABLE_DEFINITION, + SCHEMA, + SCALAR, + OBJECT, + FIELD_DEFINITION, + ARGUMENT_DEFINITION, + INTERFACE, + UNION, + ENUM, + ENUM_VALUE, + INPUT_OBJECT, + INPUT_FIELD_DEFINITION +}; + +[[nodiscard("unnecessary call")]] constexpr auto getDirectiveLocationNames() noexcept +{ + using namespace std::literals; + + return std::array { + R"gql(QUERY)gql"sv, + R"gql(MUTATION)gql"sv, + R"gql(SUBSCRIPTION)gql"sv, + R"gql(FIELD)gql"sv, + R"gql(FRAGMENT_DEFINITION)gql"sv, + R"gql(FRAGMENT_SPREAD)gql"sv, + R"gql(INLINE_FRAGMENT)gql"sv, + R"gql(VARIABLE_DEFINITION)gql"sv, + R"gql(SCHEMA)gql"sv, + R"gql(SCALAR)gql"sv, + R"gql(OBJECT)gql"sv, + R"gql(FIELD_DEFINITION)gql"sv, + R"gql(ARGUMENT_DEFINITION)gql"sv, + R"gql(INTERFACE)gql"sv, + R"gql(UNION)gql"sv, + R"gql(ENUM)gql"sv, + R"gql(ENUM_VALUE)gql"sv, + R"gql(INPUT_OBJECT)gql"sv, + R"gql(INPUT_FIELD_DEFINITION)gql"sv + }; +} + +[[nodiscard("unnecessary call")]] constexpr auto getDirectiveLocationValues() noexcept +{ + using namespace std::literals; + + return std::array, 19> { + std::make_pair(R"gql(ENUM)gql"sv, DirectiveLocation::ENUM), + std::make_pair(R"gql(FIELD)gql"sv, DirectiveLocation::FIELD), + std::make_pair(R"gql(QUERY)gql"sv, DirectiveLocation::QUERY), + std::make_pair(R"gql(UNION)gql"sv, DirectiveLocation::UNION), + std::make_pair(R"gql(OBJECT)gql"sv, DirectiveLocation::OBJECT), + std::make_pair(R"gql(SCALAR)gql"sv, DirectiveLocation::SCALAR), + std::make_pair(R"gql(SCHEMA)gql"sv, DirectiveLocation::SCHEMA), + std::make_pair(R"gql(MUTATION)gql"sv, DirectiveLocation::MUTATION), + std::make_pair(R"gql(INTERFACE)gql"sv, DirectiveLocation::INTERFACE), + std::make_pair(R"gql(ENUM_VALUE)gql"sv, DirectiveLocation::ENUM_VALUE), + std::make_pair(R"gql(INPUT_OBJECT)gql"sv, DirectiveLocation::INPUT_OBJECT), + std::make_pair(R"gql(SUBSCRIPTION)gql"sv, DirectiveLocation::SUBSCRIPTION), + std::make_pair(R"gql(FRAGMENT_SPREAD)gql"sv, DirectiveLocation::FRAGMENT_SPREAD), + std::make_pair(R"gql(INLINE_FRAGMENT)gql"sv, DirectiveLocation::INLINE_FRAGMENT), + std::make_pair(R"gql(FIELD_DEFINITION)gql"sv, DirectiveLocation::FIELD_DEFINITION), + std::make_pair(R"gql(ARGUMENT_DEFINITION)gql"sv, DirectiveLocation::ARGUMENT_DEFINITION), + std::make_pair(R"gql(FRAGMENT_DEFINITION)gql"sv, DirectiveLocation::FRAGMENT_DEFINITION), + std::make_pair(R"gql(VARIABLE_DEFINITION)gql"sv, DirectiveLocation::VARIABLE_DEFINITION), + std::make_pair(R"gql(INPUT_FIELD_DEFINITION)gql"sv, DirectiveLocation::INPUT_FIELD_DEFINITION) + }; +} + +} // namespace introspection + +namespace service { + +#ifdef GRAPHQL_DLLEXPORTS +// Export all of the built-in converters +template <> +GRAPHQLSERVICE_EXPORT introspection::TypeKind Argument::convert( + const response::Value& value); +template <> +GRAPHQLSERVICE_EXPORT AwaitableResolver Result::convert( + AwaitableScalar result, ResolverParams&& params); +template <> +GRAPHQLSERVICE_EXPORT void Result::validateScalar( + const response::Value& value); +template <> +GRAPHQLSERVICE_EXPORT introspection::DirectiveLocation Argument::convert( + const response::Value& value); +template <> +GRAPHQLSERVICE_EXPORT AwaitableResolver Result::convert( + AwaitableScalar result, ResolverParams&& params); +template <> +GRAPHQLSERVICE_EXPORT void Result::validateScalar( + const response::Value& value); +#endif // GRAPHQL_DLLEXPORTS + +} // namespace service +} // namespace graphql + +#endif // INTROSPECTIONSHAREDTYPES_H diff --git a/src/introspection/IntrospectionSharedTypes.ixx b/src/introspection/IntrospectionSharedTypes.ixx new file mode 100644 index 00000000..60538148 --- /dev/null +++ b/src/introspection/IntrospectionSharedTypes.ixx @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// WARNING! Do not edit this file manually, your changes will be overwritten. + +module; + +#include "IntrospectionSharedTypes.h" + +export module GraphQL.Introspection.IntrospectionSharedTypes; + +export namespace graphql::introspection { + +using introspection::TypeKind; +using introspection::getTypeKindNames; +using introspection::getTypeKindValues; + +using introspection::DirectiveLocation; +using introspection::getDirectiveLocationNames; +using introspection::getDirectiveLocationValues; + +} // namespace graphql::introspection diff --git a/src/introspection/introspection_schema_files b/src/introspection/introspection_schema_files index fba57600..fac4e1ee 100644 --- a/src/introspection/introspection_schema_files +++ b/src/introspection/introspection_schema_files @@ -1,3 +1,4 @@ +IntrospectionSharedTypes.cpp IntrospectionSchema.cpp SchemaObject.cpp TypeObject.cpp