Skip to content

Commit d4a91a2

Browse files
committed
Update Validation tests and schema to latest GraphQL spec
1 parent 9d14621 commit d4a91a2

11 files changed

+531
-196
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
// WARNING! Do not edit this file manually, your changes will be overwritten.
5+
6+
#include "NodeObject.h"
7+
8+
#include "graphqlservice/internal/Schema.h"
9+
10+
#include "graphqlservice/introspection/IntrospectionSchema.h"
11+
12+
using namespace std::literals;
13+
14+
namespace graphql::validation {
15+
namespace object {
16+
17+
Node::Node(std::unique_ptr<Concept>&& pimpl) noexcept
18+
: service::Object { pimpl->getTypeNames(), pimpl->getResolvers() }
19+
, _pimpl { std::move(pimpl) }
20+
{
21+
}
22+
23+
void Node::beginSelectionSet(const service::SelectionSetParams& params) const
24+
{
25+
_pimpl->beginSelectionSet(params);
26+
}
27+
28+
void Node::endSelectionSet(const service::SelectionSetParams& params) const
29+
{
30+
_pimpl->endSelectionSet(params);
31+
}
32+
33+
} // namespace object
34+
35+
void AddNodeDetails(const std::shared_ptr<schema::InterfaceType>& typeNode, const std::shared_ptr<schema::Schema>& schema)
36+
{
37+
typeNode->AddFields({
38+
schema::Field::Make(R"gql(id)gql"sv, R"md()md"sv, std::nullopt, schema->WrapType(introspection::TypeKind::NON_NULL, schema->LookupType(R"gql(ID)gql"sv)))
39+
});
40+
}
41+
42+
} // namespace graphql::validation
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
// WARNING! Do not edit this file manually, your changes will be overwritten.
5+
6+
#pragma once
7+
8+
#ifndef NODEOBJECT_H
9+
#define NODEOBJECT_H
10+
11+
#include "ValidationSchema.h"
12+
13+
namespace graphql::validation::object {
14+
15+
class Node
16+
: public service::Object
17+
{
18+
private:
19+
struct Concept
20+
{
21+
virtual ~Concept() = default;
22+
23+
virtual service::TypeNames getTypeNames() const noexcept = 0;
24+
virtual service::ResolverMap getResolvers() const noexcept = 0;
25+
26+
virtual void beginSelectionSet(const service::SelectionSetParams& params) const = 0;
27+
virtual void endSelectionSet(const service::SelectionSetParams& params) const = 0;
28+
};
29+
30+
template <class T>
31+
struct Model
32+
: Concept
33+
{
34+
Model(std::shared_ptr<T>&& pimpl) noexcept
35+
: _pimpl { std::move(pimpl) }
36+
{
37+
}
38+
39+
service::TypeNames getTypeNames() const noexcept final
40+
{
41+
return _pimpl->getTypeNames();
42+
}
43+
44+
service::ResolverMap getResolvers() const noexcept final
45+
{
46+
return _pimpl->getResolvers();
47+
}
48+
49+
void beginSelectionSet(const service::SelectionSetParams& params) const final
50+
{
51+
_pimpl->beginSelectionSet(params);
52+
}
53+
54+
void endSelectionSet(const service::SelectionSetParams& params) const final
55+
{
56+
_pimpl->endSelectionSet(params);
57+
}
58+
59+
private:
60+
const std::shared_ptr<T> _pimpl;
61+
};
62+
63+
Node(std::unique_ptr<Concept>&& pimpl) noexcept;
64+
65+
void beginSelectionSet(const service::SelectionSetParams& params) const final;
66+
void endSelectionSet(const service::SelectionSetParams& params) const final;
67+
68+
const std::unique_ptr<Concept> _pimpl;
69+
70+
public:
71+
template <class T>
72+
Node(std::shared_ptr<T> pimpl) noexcept
73+
: Node { std::unique_ptr<Concept> { std::make_unique<Model<T>>(std::move(pimpl)) } }
74+
{
75+
static_assert(T::template implements<Node>(), "Node is not implemented");
76+
}
77+
};
78+
79+
} // namespace graphql::validation::object
80+
81+
#endif // NODEOBJECT_H

samples/validation/schema/QueryObject.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "PetObject.h"
1010
#include "CatOrDogObject.h"
1111
#include "ArgumentsObject.h"
12+
#include "ResourceObject.h"
1213

1314
#include "graphqlservice/internal/Schema.h"
1415

@@ -46,6 +47,7 @@ service::ResolverMap Query::getResolvers() const noexcept
4647
{ R"gql(human)gql"sv, [this](service::ResolverParams&& params) { return resolveHuman(std::move(params)); } },
4748
{ R"gql(findDog)gql"sv, [this](service::ResolverParams&& params) { return resolveFindDog(std::move(params)); } },
4849
{ R"gql(catOrDog)gql"sv, [this](service::ResolverParams&& params) { return resolveCatOrDog(std::move(params)); } },
50+
{ R"gql(resource)gql"sv, [this](service::ResolverParams&& params) { return resolveResource(std::move(params)); } },
4951
{ R"gql(arguments)gql"sv, [this](service::ResolverParams&& params) { return resolveArguments(std::move(params)); } },
5052
{ R"gql(__typename)gql"sv, [this](service::ResolverParams&& params) { return resolve_typename(std::move(params)); } },
5153
{ R"gql(booleanList)gql"sv, [this](service::ResolverParams&& params) { return resolveBooleanList(std::move(params)); } }
@@ -112,6 +114,16 @@ service::AwaitableResolver Query::resolveArguments(service::ResolverParams&& par
112114
return service::ModifiedResult<Arguments>::convert<service::TypeModifier::Nullable>(std::move(result), std::move(params));
113115
}
114116

117+
service::AwaitableResolver Query::resolveResource(service::ResolverParams&& params) const
118+
{
119+
std::unique_lock resolverLock(_resolverMutex);
120+
auto directives = std::move(params.fieldDirectives);
121+
auto result = _pimpl->getResource(service::FieldParams(service::SelectionSetParams{ params }, std::move(directives)));
122+
resolverLock.unlock();
123+
124+
return service::ModifiedResult<Resource>::convert<service::TypeModifier::Nullable>(std::move(result), std::move(params));
125+
}
126+
115127
service::AwaitableResolver Query::resolveFindDog(service::ResolverParams&& params) const
116128
{
117129
auto argComplex = service::ModifiedArgument<validation::ComplexInput>::require<service::TypeModifier::Nullable>("complex", params.arguments);
@@ -149,6 +161,7 @@ void AddQueryDetails(const std::shared_ptr<schema::ObjectType>& typeQuery, const
149161
schema::Field::Make(R"gql(pet)gql"sv, R"md()md"sv, std::nullopt, schema->LookupType(R"gql(Pet)gql"sv)),
150162
schema::Field::Make(R"gql(catOrDog)gql"sv, R"md()md"sv, std::nullopt, schema->LookupType(R"gql(CatOrDog)gql"sv)),
151163
schema::Field::Make(R"gql(arguments)gql"sv, R"md()md"sv, std::nullopt, schema->LookupType(R"gql(Arguments)gql"sv)),
164+
schema::Field::Make(R"gql(resource)gql"sv, R"md()md"sv, std::nullopt, schema->LookupType(R"gql(Resource)gql"sv)),
152165
schema::Field::Make(R"gql(findDog)gql"sv, R"md()md"sv, std::nullopt, schema->LookupType(R"gql(Dog)gql"sv), {
153166
schema::InputValue::Make(R"gql(complex)gql"sv, R"md()md"sv, schema->LookupType(R"gql(ComplexInput)gql"sv), R"gql()gql"sv)
154167
}),

samples/validation/schema/QueryObject.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,18 @@ concept getArguments = requires (TImpl impl)
7373
{ service::FieldResult<std::shared_ptr<Arguments>> { impl.getArguments() } };
7474
};
7575

76+
template <class TImpl>
77+
concept getResourceWithParams = requires (TImpl impl, service::FieldParams params)
78+
{
79+
{ service::FieldResult<std::shared_ptr<Resource>> { impl.getResource(std::move(params)) } };
80+
};
81+
82+
template <class TImpl>
83+
concept getResource = requires (TImpl impl)
84+
{
85+
{ service::FieldResult<std::shared_ptr<Resource>> { impl.getResource() } };
86+
};
87+
7688
template <class TImpl>
7789
concept getFindDogWithParams = requires (TImpl impl, service::FieldParams params, std::optional<ComplexInput> complexArg)
7890
{
@@ -120,6 +132,7 @@ class Query
120132
service::AwaitableResolver resolvePet(service::ResolverParams&& params) const;
121133
service::AwaitableResolver resolveCatOrDog(service::ResolverParams&& params) const;
122134
service::AwaitableResolver resolveArguments(service::ResolverParams&& params) const;
135+
service::AwaitableResolver resolveResource(service::ResolverParams&& params) const;
123136
service::AwaitableResolver resolveFindDog(service::ResolverParams&& params) const;
124137
service::AwaitableResolver resolveBooleanList(service::ResolverParams&& params) const;
125138

@@ -137,6 +150,7 @@ class Query
137150
virtual service::FieldResult<std::shared_ptr<Pet>> getPet(service::FieldParams&& params) const = 0;
138151
virtual service::FieldResult<std::shared_ptr<CatOrDog>> getCatOrDog(service::FieldParams&& params) const = 0;
139152
virtual service::FieldResult<std::shared_ptr<Arguments>> getArguments(service::FieldParams&& params) const = 0;
153+
virtual service::FieldResult<std::shared_ptr<Resource>> getResource(service::FieldParams&& params) const = 0;
140154
virtual service::FieldResult<std::shared_ptr<Dog>> getFindDog(service::FieldParams&& params, std::optional<ComplexInput>&& complexArg) const = 0;
141155
virtual service::FieldResult<std::optional<bool>> getBooleanList(service::FieldParams&& params, std::optional<std::vector<bool>>&& booleanListArgArg) const = 0;
142156
};
@@ -230,6 +244,22 @@ class Query
230244
}
231245
}
232246

247+
service::FieldResult<std::shared_ptr<Resource>> getResource(service::FieldParams&& params) const final
248+
{
249+
if constexpr (methods::QueryHas::getResourceWithParams<T>)
250+
{
251+
return { _pimpl->getResource(std::move(params)) };
252+
}
253+
else if constexpr (methods::QueryHas::getResource<T>)
254+
{
255+
return { _pimpl->getResource() };
256+
}
257+
else
258+
{
259+
throw std::runtime_error(R"ex(Query::getResource is not implemented)ex");
260+
}
261+
}
262+
233263
service::FieldResult<std::shared_ptr<Dog>> getFindDog(service::FieldParams&& params, std::optional<ComplexInput>&& complexArg) const final
234264
{
235265
if constexpr (methods::QueryHas::getFindDogWithParams<T>)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
// WARNING! Do not edit this file manually, your changes will be overwritten.
5+
6+
#include "ResourceObject.h"
7+
8+
#include "graphqlservice/internal/Schema.h"
9+
10+
#include "graphqlservice/introspection/IntrospectionSchema.h"
11+
12+
using namespace std::literals;
13+
14+
namespace graphql::validation {
15+
namespace object {
16+
17+
Resource::Resource(std::unique_ptr<Concept>&& pimpl) noexcept
18+
: service::Object { pimpl->getTypeNames(), pimpl->getResolvers() }
19+
, _pimpl { std::move(pimpl) }
20+
{
21+
}
22+
23+
void Resource::beginSelectionSet(const service::SelectionSetParams& params) const
24+
{
25+
_pimpl->beginSelectionSet(params);
26+
}
27+
28+
void Resource::endSelectionSet(const service::SelectionSetParams& params) const
29+
{
30+
_pimpl->endSelectionSet(params);
31+
}
32+
33+
} // namespace object
34+
35+
void AddResourceDetails(const std::shared_ptr<schema::InterfaceType>& typeResource, const std::shared_ptr<schema::Schema>& schema)
36+
{
37+
typeResource->AddInterfaces({
38+
std::static_pointer_cast<const schema::InterfaceType>(schema->LookupType(R"gql(Node)gql"sv))
39+
});
40+
typeResource->AddFields({
41+
schema::Field::Make(R"gql(id)gql"sv, R"md()md"sv, std::nullopt, schema->WrapType(introspection::TypeKind::NON_NULL, schema->LookupType(R"gql(ID)gql"sv))),
42+
schema::Field::Make(R"gql(url)gql"sv, R"md()md"sv, std::nullopt, schema->LookupType(R"gql(String)gql"sv))
43+
});
44+
}
45+
46+
} // namespace graphql::validation
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
// WARNING! Do not edit this file manually, your changes will be overwritten.
5+
6+
#pragma once
7+
8+
#ifndef RESOURCEOBJECT_H
9+
#define RESOURCEOBJECT_H
10+
11+
#include "ValidationSchema.h"
12+
13+
namespace graphql::validation::object {
14+
15+
class Resource
16+
: public service::Object
17+
{
18+
private:
19+
struct Concept
20+
{
21+
virtual ~Concept() = default;
22+
23+
virtual service::TypeNames getTypeNames() const noexcept = 0;
24+
virtual service::ResolverMap getResolvers() const noexcept = 0;
25+
26+
virtual void beginSelectionSet(const service::SelectionSetParams& params) const = 0;
27+
virtual void endSelectionSet(const service::SelectionSetParams& params) const = 0;
28+
};
29+
30+
template <class T>
31+
struct Model
32+
: Concept
33+
{
34+
Model(std::shared_ptr<T>&& pimpl) noexcept
35+
: _pimpl { std::move(pimpl) }
36+
{
37+
}
38+
39+
service::TypeNames getTypeNames() const noexcept final
40+
{
41+
return _pimpl->getTypeNames();
42+
}
43+
44+
service::ResolverMap getResolvers() const noexcept final
45+
{
46+
return _pimpl->getResolvers();
47+
}
48+
49+
void beginSelectionSet(const service::SelectionSetParams& params) const final
50+
{
51+
_pimpl->beginSelectionSet(params);
52+
}
53+
54+
void endSelectionSet(const service::SelectionSetParams& params) const final
55+
{
56+
_pimpl->endSelectionSet(params);
57+
}
58+
59+
private:
60+
const std::shared_ptr<T> _pimpl;
61+
};
62+
63+
Resource(std::unique_ptr<Concept>&& pimpl) noexcept;
64+
65+
void beginSelectionSet(const service::SelectionSetParams& params) const final;
66+
void endSelectionSet(const service::SelectionSetParams& params) const final;
67+
68+
const std::unique_ptr<Concept> _pimpl;
69+
70+
public:
71+
template <class T>
72+
Resource(std::shared_ptr<T> pimpl) noexcept
73+
: Resource { std::unique_ptr<Concept> { std::make_unique<Model<T>>(std::move(pimpl)) } }
74+
{
75+
static_assert(T::template implements<Resource>(), "Resource is not implemented");
76+
}
77+
};
78+
79+
} // namespace graphql::validation::object
80+
81+
#endif // RESOURCEOBJECT_H

samples/validation/schema/ValidationSchema.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,10 @@ void AddTypesToSchema(const std::shared_ptr<schema::Schema>& schema)
139139
schema->AddType(R"gql(Sentient)gql"sv, typeSentient);
140140
auto typePet = schema::InterfaceType::Make(R"gql(Pet)gql"sv, R"md()md"sv);
141141
schema->AddType(R"gql(Pet)gql"sv, typePet);
142+
auto typeNode = schema::InterfaceType::Make(R"gql(Node)gql"sv, R"md()md"sv);
143+
schema->AddType(R"gql(Node)gql"sv, typeNode);
144+
auto typeResource = schema::InterfaceType::Make(R"gql(Resource)gql"sv, R"md()md"sv);
145+
schema->AddType(R"gql(Resource)gql"sv, typeResource);
142146
auto typeCatOrDog = schema::UnionType::Make(R"gql(CatOrDog)gql"sv, R"md()md"sv);
143147
schema->AddType(R"gql(CatOrDog)gql"sv, typeCatOrDog);
144148
auto typeDogOrHuman = schema::UnionType::Make(R"gql(DogOrHuman)gql"sv, R"md()md"sv);
@@ -182,6 +186,8 @@ void AddTypesToSchema(const std::shared_ptr<schema::Schema>& schema)
182186

183187
AddSentientDetails(typeSentient, schema);
184188
AddPetDetails(typePet, schema);
189+
AddNodeDetails(typeNode, schema);
190+
AddResourceDetails(typeResource, schema);
185191

186192
AddCatOrDogDetails(typeCatOrDog, schema);
187193
AddDogOrHumanDetails(typeDogOrHuman, schema);

samples/validation/schema/ValidationSchema.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ namespace object {
4343

4444
class Sentient;
4545
class Pet;
46+
class Node;
47+
class Resource;
4648

4749
class CatOrDog;
4850
class DogOrHuman;
@@ -81,6 +83,8 @@ class Operations
8183

8284
void AddSentientDetails(const std::shared_ptr<schema::InterfaceType>& typeSentient, const std::shared_ptr<schema::Schema>& schema);
8385
void AddPetDetails(const std::shared_ptr<schema::InterfaceType>& typePet, const std::shared_ptr<schema::Schema>& schema);
86+
void AddNodeDetails(const std::shared_ptr<schema::InterfaceType>& typeNode, const std::shared_ptr<schema::Schema>& schema);
87+
void AddResourceDetails(const std::shared_ptr<schema::InterfaceType>& typeResource, const std::shared_ptr<schema::Schema>& schema);
8488

8589
void AddCatOrDogDetails(const std::shared_ptr<schema::UnionType>& typeCatOrDog, const std::shared_ptr<schema::Schema>& schema);
8690
void AddDogOrHumanDetails(const std::shared_ptr<schema::UnionType>& typeDogOrHuman, const std::shared_ptr<schema::Schema>& schema);

0 commit comments

Comments
 (0)