Skip to content

Commit

Permalink
Merge pull request #327 from wravery/schema-stitch
Browse files Browse the repository at this point in the history
fix: #323
  • Loading branch information
wravery authored Oct 21, 2024
2 parents a610521 + 8b0102c commit e85fc7e
Show file tree
Hide file tree
Showing 16 changed files with 909 additions and 28 deletions.
8 changes: 8 additions & 0 deletions include/graphqlservice/GraphQLService.h
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,9 @@ class [[nodiscard("unnecessary construction")]] Object : public std::enable_shar
GRAPHQLSERVICE_EXPORT explicit Object(TypeNames&& typeNames, ResolverMap&& resolvers) noexcept;
GRAPHQLSERVICE_EXPORT virtual ~Object() = default;

[[nodiscard("unnecessary call")]] GRAPHQLSERVICE_EXPORT std::shared_ptr<Object> StitchObject(
const std::shared_ptr<const Object>& added) const;

[[nodiscard("unnecessary call")]] GRAPHQLSERVICE_EXPORT AwaitableResolver resolve(
const SelectionSetParams& selectionSetParams, const peg::ast_node& selection,
const FragmentMap& fragments, const response::Value& variables) const;
Expand All @@ -846,6 +849,7 @@ class [[nodiscard("unnecessary construction")]] Object : public std::enable_shar
private:
TypeNames _typeNames;
ResolverMap _resolvers;
std::vector<std::shared_ptr<const Object>> _stitched;
};

// Test if this Type inherits from Object.
Expand Down Expand Up @@ -1440,6 +1444,9 @@ class [[nodiscard("unnecessary construction")]] Request
GRAPHQLSERVICE_EXPORT virtual ~Request();

public:
[[nodiscard("unnecessary call")]] GRAPHQLSERVICE_EXPORT std::shared_ptr<const Request> stitch(
const std::shared_ptr<const Request>& added) const;

[[nodiscard("unnecessary call")]] GRAPHQLSERVICE_EXPORT std::list<schema_error> validate(
peg::ast& query) const;

Expand All @@ -1466,6 +1473,7 @@ class [[nodiscard("unnecessary construction")]] Request
collectRegistrations(std::string_view field, RequestDeliverFilter&& filter) const noexcept;

const TypeMap _operations;
const std::shared_ptr<schema::Schema> _schema;
mutable std::mutex _validationMutex {};
const std::unique_ptr<ValidateExecutableVisitor> _validation;
mutable std::mutex _subscriptionMutex {};
Expand Down
6 changes: 6 additions & 0 deletions include/graphqlservice/internal/Schema.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ class [[nodiscard("unnecessary construction")]] Schema : public std::enable_shar
GRAPHQLSERVICE_EXPORT explicit Schema(
bool noIntrospection = false, std::string_view description = "");

[[nodiscard("unnecessary call")]] GRAPHQLSERVICE_EXPORT std::shared_ptr<Schema> StitchSchema(
const std::shared_ptr<const Schema>& added) const;

GRAPHQLSERVICE_EXPORT void AddQueryType(std::shared_ptr<ObjectType> query);
GRAPHQLSERVICE_EXPORT void AddMutationType(std::shared_ptr<ObjectType> mutation);
GRAPHQLSERVICE_EXPORT void AddSubscriptionType(std::shared_ptr<ObjectType> subscription);
Expand Down Expand Up @@ -74,6 +77,9 @@ class [[nodiscard("unnecessary construction")]] Schema : public std::enable_shar
directives() const noexcept;

private:
[[nodiscard("unnecessary call")]] std::shared_ptr<const BaseType> StitchFieldType(
std::shared_ptr<const BaseType> fieldType);

const bool _noIntrospection = false;
const std::string_view _description;

Expand Down
5 changes: 5 additions & 0 deletions samples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ endif()

add_subdirectory(client)
add_subdirectory(learn)

if(GRAPHQL_BUILD_MODULES)
add_subdirectory(stitched)
endif()

add_subdirectory(validation)

if(GRAPHQL_BUILD_HTTP_SAMPLE)
Expand Down
22 changes: 14 additions & 8 deletions samples/learn/StarWarsData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ using namespace std::literals;

namespace graphql::star_wars {

std::shared_ptr<service::Request> GetService() noexcept
std::shared_ptr<learn::object::Query> MakeQuery() noexcept
{
auto luke = std::make_shared<learn::Human>("1000"s,
std::make_optional("Luke Skywalker"s),
Expand Down Expand Up @@ -111,14 +111,20 @@ std::shared_ptr<service::Request> GetService() noexcept
{ artoo->getId(), artoo },
};

auto query =
std::make_shared<learn::Query>(std::move(heroes), std::move(humans), std::move(droids));
auto mutation = std::make_shared<learn::Mutation>();
auto service = std::make_shared<learn::Operations>(std::move(query),
std::move(mutation),
std::shared_ptr<learn::Subscription> {});
return std::make_shared<learn::object::Query>(
std::make_shared<learn::Query>(std::move(heroes), std::move(humans), std::move(droids)));
}

return service;
std::shared_ptr<learn::object::Mutation> MakeMutation() noexcept
{
return std::make_shared<learn::object::Mutation>(std::make_shared<learn::Mutation>());
}

std::shared_ptr<service::Request> GetService() noexcept
{
return std::make_shared<learn::Operations>(MakeQuery(),
MakeMutation(),
std::shared_ptr<learn::object::Subscription> {});
}

} // namespace graphql::star_wars
34 changes: 34 additions & 0 deletions samples/stitched/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

cmake_minimum_required(VERSION 3.28)

add_library(stitchedschema STATIC
StitchedSchema.cpp)
target_link_libraries(stitchedschema PUBLIC star_wars todaygraphql)
target_include_directories(stitchedschema INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

add_executable(stitched sample.cpp)
target_link_libraries(stitched PRIVATE
stitchedschema
graphqljson)

if(WIN32 AND BUILD_SHARED_LIBS)
add_custom_command(OUTPUT copied_sample_dlls
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:graphqlservice>
$<TARGET_FILE:graphqljson>
$<TARGET_FILE:graphqlpeg>
$<TARGET_FILE:graphqlresponse>
${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E touch copied_sample_dlls
DEPENDS
graphqlservice
graphqljson
graphqlpeg
graphqlresponse)

add_custom_target(copy_stitched_sample_dlls DEPENDS copied_sample_dlls)

add_dependencies(stitched copy_stitched_sample_dlls)
endif()
18 changes: 18 additions & 0 deletions samples/stitched/StitchedSchema.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#include "StitchedSchema.h"

#include "StarWarsData.h"
#include "StarWarsSchema.h"

import GraphQL.Today.Mock;

namespace graphql::stitched {

std::shared_ptr<const service::Request> GetService()
{
return star_wars::GetService()->stitch(today::mock_service()->service);
}

} // namespace graphql::stitched
20 changes: 20 additions & 0 deletions samples/stitched/StitchedSchema.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#pragma once

#ifndef STITCHEDSCHEMA_H
#define STITCHEDSCHEMA_H

#include "graphqlservice/GraphQLService.h"

#include "StarWarsSharedTypes.h"
#include "TodaySharedTypes.h"

namespace graphql::stitched {

std::shared_ptr<const service::Request> GetService();

} // namespace graphql::stitched

#endif // STITCHEDSCHEMA_H
57 changes: 57 additions & 0 deletions samples/stitched/sample.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#include "StitchedSchema.h"

#include "graphqlservice/JSONResponse.h"

#include <cstdio>
#include <iostream>
#include <iterator>
#include <stdexcept>

using namespace graphql;

int main(int argc, char** argv)
{
auto service = stitched::GetService();

std::cout << "Created the service..." << std::endl;

try
{
peg::ast query;

if (argc > 1)
{
query = peg::parseFile(argv[1]);
}
else
{
std::istream_iterator<char> start { std::cin >> std::noskipws }, end {};
std::string input { start, end };

query = peg::parseString(std::move(input));
}

if (!query.root)
{
std::cerr << "Unknown error!" << std::endl;
std::cerr << std::endl;
return 1;
}

std::cout << "Executing query..." << std::endl;

std::cout << response::toJSON(
service->resolve({ query, ((argc > 2) ? argv[2] : "") }).get())
<< std::endl;
}
catch (const std::runtime_error& ex)
{
std::cerr << ex.what() << std::endl;
return 1;
}

return 0;
}
49 changes: 34 additions & 15 deletions samples/today/TodayMock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,47 +62,66 @@ const response::IdType& getFakeFolderId() noexcept
return s_fakeId;
}

std::unique_ptr<TodayMockService> mock_service() noexcept
std::shared_ptr<Query> mock_query(const std::shared_ptr<TodayMockService>& service) noexcept
{
auto result = std::make_unique<TodayMockService>();

auto query = std::make_shared<Query>(
[mockService = result.get()]() -> std::vector<std::shared_ptr<Appointment>> {
++mockService->getAppointmentsCount;
return std::make_shared<Query>(
[weakService = std::weak_ptr { service }]() -> std::vector<std::shared_ptr<Appointment>> {
if (auto mockService = weakService.lock())
{
++mockService->getAppointmentsCount;
}
return { std::make_shared<Appointment>(response::IdType(getFakeAppointmentId()),
"tomorrow",
"Lunch?",
false) };
},
[mockService = result.get()]() -> std::vector<std::shared_ptr<Task>> {
++mockService->getTasksCount;
[weakService = std::weak_ptr { service }]() -> std::vector<std::shared_ptr<Task>> {
if (auto mockService = weakService.lock())
{
++mockService->getTasksCount;
}
return {
std::make_shared<Task>(response::IdType(getFakeTaskId()), "Don't forget", true)
};
},
[mockService = result.get()]() -> std::vector<std::shared_ptr<Folder>> {
++mockService->getUnreadCountsCount;
[weakService = std::weak_ptr { service }]() -> std::vector<std::shared_ptr<Folder>> {
if (auto mockService = weakService.lock())
{
++mockService->getUnreadCountsCount;
}
return {
std::make_shared<Folder>(response::IdType(getFakeFolderId()), "\"Fake\" Inbox", 3)
};
});
auto mutation = std::make_shared<Mutation>(
}

std::shared_ptr<Mutation> mock_mutation() noexcept
{
return std::make_shared<Mutation>(
[](CompleteTaskInput&& input) -> std::shared_ptr<CompleteTaskPayload> {
return std::make_shared<CompleteTaskPayload>(
std::make_shared<Task>(std::move(input.id), "Mutated Task!", *(input.isComplete)),
std::move(input.clientMutationId));
});
auto subscription = std::make_shared<NextAppointmentChange>(
}

std::shared_ptr<NextAppointmentChange> mock_subscription() noexcept
{
return std::make_shared<NextAppointmentChange>(
[](const std::shared_ptr<service::RequestState>&) -> std::shared_ptr<Appointment> {
return { std::make_shared<Appointment>(response::IdType(getFakeAppointmentId()),
"tomorrow",
"Lunch?",
true) };
});
}

std::shared_ptr<TodayMockService> mock_service() noexcept
{
auto result = std::make_shared<TodayMockService>();

result->service = std::make_shared<Operations>(std::move(query),
std::move(mutation),
std::move(subscription));
result->service =
std::make_shared<Operations>(mock_query(result), mock_mutation(), mock_subscription());

return result;
}
Expand Down
2 changes: 1 addition & 1 deletion samples/today/TodayMock.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ struct TodayMockService
std::size_t getUnreadCountsCount {};
};

std::unique_ptr<TodayMockService> mock_service() noexcept;
std::shared_ptr<TodayMockService> mock_service() noexcept;

struct RequestState : service::RequestState
{
Expand Down
Loading

0 comments on commit e85fc7e

Please sign in to comment.