Skip to content

Commit 0bc5c6c

Browse files
committed
Split validation into separate files to prep for refactoring
1 parent 8bfefdc commit 0bc5c6c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+2026
-1984
lines changed

include/SchemaGenerator.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
#ifndef SCHEMAGENERATOR_H
77
#define SCHEMAGENERATOR_H
88

9-
#include <graphqlservice/GraphQLService.h>
10-
#include <graphqlservice/GraphQLGrammar.h>
9+
#include "graphqlservice/GraphQLService.h"
10+
#include "graphqlservice/GraphQLGrammar.h"
1111

1212
#include <array>
1313
#include <cstdio>

include/Validation.h

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
#pragma once
5+
6+
#ifndef VALIDATION_H
7+
#define VALIDATION_H
8+
9+
#include "graphqlservice/GraphQLService.h"
10+
#include "graphqlservice/IntrospectionSchema.h"
11+
12+
namespace graphql::service {
13+
14+
using ValidateType = response::Value;
15+
16+
struct ValidateArgument
17+
{
18+
bool defaultValue = false;
19+
ValidateType type;
20+
};
21+
22+
using ValidateTypeFieldArguments = std::map<std::string, ValidateArgument>;
23+
24+
struct ValidateTypeField
25+
{
26+
ValidateType returnType;
27+
ValidateTypeFieldArguments arguments;
28+
};
29+
30+
using ValidateDirectiveArguments = std::map<std::string, ValidateArgument>;
31+
32+
struct ValidateDirective
33+
{
34+
std::set<introspection::DirectiveLocation> locations;
35+
ValidateDirectiveArguments arguments;
36+
};
37+
38+
struct ValidateArgumentVariable
39+
{
40+
bool operator==(const ValidateArgumentVariable& other) const;
41+
42+
std::string name;
43+
};
44+
45+
struct ValidateArgumentEnumValue
46+
{
47+
bool operator==(const ValidateArgumentEnumValue& other) const;
48+
49+
std::string value;
50+
};
51+
52+
struct ValidateArgumentValue;
53+
54+
struct ValidateArgumentValuePtr
55+
{
56+
bool operator==(const ValidateArgumentValuePtr& other) const;
57+
58+
std::unique_ptr<ValidateArgumentValue> value;
59+
schema_location position;
60+
};
61+
62+
struct ValidateArgumentList
63+
{
64+
bool operator==(const ValidateArgumentList& other) const;
65+
66+
std::vector<ValidateArgumentValuePtr> values;
67+
};
68+
69+
struct ValidateArgumentMap
70+
{
71+
bool operator==(const ValidateArgumentMap& other) const;
72+
73+
std::map<std::string, ValidateArgumentValuePtr> values;
74+
};
75+
76+
using ValidateArgumentVariant = std::variant<
77+
ValidateArgumentVariable,
78+
response::IntType,
79+
response::FloatType,
80+
response::StringType,
81+
response::BooleanType,
82+
ValidateArgumentEnumValue,
83+
ValidateArgumentList,
84+
ValidateArgumentMap>;
85+
86+
struct ValidateArgumentValue
87+
{
88+
ValidateArgumentValue(ValidateArgumentVariable&& value);
89+
ValidateArgumentValue(response::IntType value);
90+
ValidateArgumentValue(response::FloatType value);
91+
ValidateArgumentValue(response::StringType&& value);
92+
ValidateArgumentValue(response::BooleanType value);
93+
ValidateArgumentValue(ValidateArgumentEnumValue&& value);
94+
ValidateArgumentValue(ValidateArgumentList&& value);
95+
ValidateArgumentValue(ValidateArgumentMap&& value);
96+
97+
ValidateArgumentVariant data;
98+
};
99+
100+
// ValidateArgumentValueVisitor visits the AST and builds a record of a field return type and map
101+
// of the arguments for comparison to see if 2 fields with the same result name can be merged.
102+
class ValidateArgumentValueVisitor
103+
{
104+
public:
105+
ValidateArgumentValueVisitor();
106+
107+
void visit(const peg::ast_node& value);
108+
109+
ValidateArgumentValuePtr getArgumentValue();
110+
111+
private:
112+
void visitVariable(const peg::ast_node& variable);
113+
void visitIntValue(const peg::ast_node& intValue);
114+
void visitFloatValue(const peg::ast_node& floatValue);
115+
void visitStringValue(const peg::ast_node& stringValue);
116+
void visitBooleanValue(const peg::ast_node& booleanValue);
117+
void visitNullValue(const peg::ast_node& nullValue);
118+
void visitEnumValue(const peg::ast_node& enumValue);
119+
void visitListValue(const peg::ast_node& listValue);
120+
void visitObjectValue(const peg::ast_node& objectValue);
121+
122+
ValidateArgumentValuePtr _argumentValue;
123+
};
124+
125+
using ValidateFieldArguments = std::map<std::string, ValidateArgumentValuePtr>;
126+
127+
struct ValidateField
128+
{
129+
ValidateField(std::string&& returnType, std::optional<std::string>&& objectType, const std::string& fieldName, ValidateFieldArguments&& arguments);
130+
131+
bool operator==(const ValidateField& other) const;
132+
133+
std::string returnType;
134+
std::optional<std::string> objectType;
135+
std::string fieldName;
136+
ValidateFieldArguments arguments;
137+
};
138+
139+
// ValidateExecutableVisitor visits the AST and validates that it is executable against the service schema.
140+
class ValidateExecutableVisitor
141+
{
142+
public:
143+
ValidateExecutableVisitor(const Request& service);
144+
145+
void visit(const peg::ast_node& root);
146+
147+
std::vector<schema_error> getStructuredErrors();
148+
149+
private:
150+
response::Value executeQuery(std::string_view query) const;
151+
152+
static ValidateTypeFieldArguments getArguments(response::ListType&& argumentsMember);
153+
154+
using FieldTypes = std::map<std::string, ValidateTypeField>;
155+
using TypeFields = std::map<std::string, FieldTypes>;
156+
157+
std::optional<introspection::TypeKind> getScopedTypeKind() const;
158+
TypeFields::const_iterator getScopedTypeFields();
159+
static std::string getFieldType(const FieldTypes& fields, const std::string& name);
160+
static std::string getWrappedFieldType(const FieldTypes& fields, const std::string& name);
161+
static std::string getWrappedFieldType(const ValidateType& returnType);
162+
163+
void visitFragmentDefinition(const peg::ast_node& fragmentDefinition);
164+
void visitOperationDefinition(const peg::ast_node& operationDefinition);
165+
166+
void visitSelection(const peg::ast_node& selection);
167+
168+
void visitField(const peg::ast_node& field);
169+
void visitFragmentSpread(const peg::ast_node& fragmentSpread);
170+
void visitInlineFragment(const peg::ast_node& inlineFragment);
171+
172+
void visitDirectives(introspection::DirectiveLocation location, const peg::ast_node& directives);
173+
174+
const Request& _service;
175+
std::vector<schema_error> _errors;
176+
177+
using OperationTypes = std::map<std::string_view, std::string>;
178+
using TypeKinds = std::map<std::string, introspection::TypeKind>;
179+
using Directives = std::map<std::string, ValidateDirective>;
180+
using ExecutableNodes = std::map<std::string, const peg::ast_node&>;
181+
using FragmentSet = std::unordered_set<std::string>;
182+
183+
OperationTypes _operationTypes;
184+
TypeKinds _typeKinds;
185+
Directives _directives;
186+
187+
ExecutableNodes _fragmentDefinitions;
188+
ExecutableNodes _operationDefinitions;
189+
190+
FragmentSet _referencedFragments;
191+
FragmentSet _fragmentStack;
192+
FragmentSet _fragmentCycles;
193+
size_t _fieldCount = 0;
194+
TypeFields _typeFields;
195+
std::string _scopedType;
196+
std::map<std::string, ValidateField> _selectionFields;
197+
};
198+
199+
} /* namespace graphql::service */
200+
201+
#endif // VALIDATION_H

include/graphqlservice/GraphQLGrammar.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#ifndef GRAPHQLGRAMMAR_H
1010
#define GRAPHQLGRAMMAR_H
1111

12-
#include <graphqlservice/GraphQLTree.h>
12+
#include "graphqlservice/GraphQLTree.h"
1313

1414
#define TAO_PEGTL_NAMESPACE tao::graphqlpeg
1515

include/graphqlservice/GraphQLService.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
#ifndef GRAPHQLSERVICE_H
77
#define GRAPHQLSERVICE_H
88

9-
#include <graphqlservice/GraphQLParse.h>
10-
#include <graphqlservice/GraphQLResponse.h>
9+
#include "graphqlservice/GraphQLParse.h"
10+
#include "graphqlservice/GraphQLResponse.h"
1111

1212
#include <memory>
1313
#include <optional>
@@ -52,6 +52,8 @@ struct schema_error
5252
field_path path;
5353
};
5454

55+
response::Value buildErrorValues(const std::vector<schema_error>& structuredErrors);
56+
5557
// This exception bubbles up 1 or more error messages to the JSON results.
5658
class schema_exception : public std::exception
5759
{
@@ -803,11 +805,6 @@ class Request : public std::enable_shared_from_this<Request>
803805

804806
std::pair<std::string, const peg::ast_node*> findOperationDefinition(const peg::ast_node& root, const std::string& operationName) const;
805807

806-
[[deprecated("Use the Request::resolve overload which takes a peg::ast reference instead.")]]
807-
std::future<response::Value> resolve(const std::shared_ptr<RequestState>& state, const peg::ast_node& root, const std::string& operationName, response::Value&& variables) const;
808-
[[deprecated("Use the Request::resolve overload which takes a peg::ast reference instead.")]]
809-
std::future<response::Value> resolve(std::launch launch, const std::shared_ptr<RequestState>& state, const peg::ast_node& root, const std::string& operationName, response::Value&& variables) const;
810-
811808
std::future<response::Value> resolve(const std::shared_ptr<RequestState>& state, peg::ast& query, const std::string& operationName, response::Value&& variables) const;
812809
std::future<response::Value> resolve(std::launch launch, const std::shared_ptr<RequestState>& state, peg::ast& query, const std::string& operationName, response::Value&& variables) const;
813810

@@ -822,6 +819,11 @@ class Request : public std::enable_shared_from_this<Request>
822819
void deliver(std::launch launch, const SubscriptionName& name, const SubscriptionArguments& arguments, const std::shared_ptr<Object>& subscriptionObject) const;
823820
void deliver(std::launch launch, const SubscriptionName& name, const SubscriptionFilterCallback& apply, const std::shared_ptr<Object>& subscriptionObject) const;
824821

822+
[[deprecated("Use the Request::resolve overload which takes a peg::ast reference instead.")]]
823+
std::future<response::Value> resolve(const std::shared_ptr<RequestState>& state, const peg::ast_node& root, const std::string& operationName, response::Value&& variables) const;
824+
[[deprecated("Use the Request::resolve overload which takes a peg::ast reference instead.")]]
825+
std::future<response::Value> resolve(std::launch launch, const std::shared_ptr<RequestState>& state, const peg::ast_node& root, const std::string& operationName, response::Value&& variables) const;
826+
825827
private:
826828
std::future<response::Value> resolveValidated(std::launch launch, const std::shared_ptr<RequestState>& state, const peg::ast_node& root, const std::string& operationName, response::Value&& variables) const;
827829

include/graphqlservice/Introspection.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#ifndef INTROSPECTION_H
77
#define INTROSPECTION_H
88

9-
#include <graphqlservice/IntrospectionSchema.h>
9+
#include "graphqlservice/IntrospectionSchema.h"
1010

1111
namespace graphql::introspection {
1212

include/graphqlservice/JSONResponse.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#ifndef JSONRESPONSE_H
77
#define JSONRESPONSE_H
88

9-
#include <graphqlservice/GraphQLResponse.h>
9+
#include "graphqlservice/GraphQLResponse.h"
1010

1111
namespace graphql::response {
1212

samples/introspection/IntrospectionSchema.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33

4-
#include <graphqlservice/Introspection.h>
4+
#include "graphqlservice/Introspection.h"
55

66
#include <algorithm>
77
#include <functional>

samples/introspection/IntrospectionSchema.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#ifndef INTROSPECTIONSCHEMA_H
77
#define INTROSPECTIONSCHEMA_H
88

9-
#include <graphqlservice/GraphQLService.h>
9+
#include "graphqlservice/GraphQLService.h"
1010

1111
#include <memory>
1212
#include <string>

samples/separate/AppointmentConnectionObject.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
#include "TodayObjects.h"
55

6-
#include <graphqlservice/Introspection.h>
6+
#include "graphqlservice/Introspection.h"
77

88
#include <algorithm>
99
#include <functional>

samples/separate/AppointmentEdgeObject.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
#include "TodayObjects.h"
55

6-
#include <graphqlservice/Introspection.h>
6+
#include "graphqlservice/Introspection.h"
77

88
#include <algorithm>
99
#include <functional>

0 commit comments

Comments
 (0)