66#ifndef CLIENTGENERATOR_H
77#define CLIENTGENERATOR_H
88
9- #include " graphqlservice/GraphQLGrammar.h"
10- #include " graphqlservice/GraphQLParse.h"
11- #include " graphqlservice/GraphQLResponse.h"
12- #include " graphqlservice/GraphQLSchema.h"
13-
14- #include < array>
15- #include < cstdio>
16- #include < unordered_map>
17- #include < unordered_set>
18-
19- namespace graphql ::client {
20-
21- // These are the set of built-in types in GraphQL.
22- enum class BuiltinType
23- {
24- Int,
25- Float,
26- String,
27- Boolean,
28- ID,
29- };
30-
31- using BuiltinTypeMap = std::map<std::string_view, BuiltinType>;
32-
33- // These are the C++ types we'll use for them.
34- using CppTypeMap = std::array<std::string_view, static_cast <size_t >(BuiltinType::ID) + 1 >;
35-
36- // Types that we understand and use to generate the skeleton of a service.
37- enum class SchemaType
38- {
39- Scalar,
40- Enum,
41- Input,
42- Union,
43- Interface,
44- Object,
45- Operation,
46- };
47-
48- using SchemaTypeMap = std::map<std::string_view, SchemaType>;
49-
50- // Keep track of the positions of each type declaration in the file.
51- using PositionMap = std::unordered_map<std::string_view, tao::graphqlpeg::position>;
52-
53- // For all of the named types we track, we want to keep them in order in a vector but
54- // be able to lookup their offset quickly by name.
55- using TypeNameMap = std::unordered_map<std::string_view, size_t >;
56-
57- // Any type can also have a list and/or non-nullable wrapper, and those can be nested.
58- // Since it's easier to express nullability than non-nullability in C++, we'll invert
59- // the presence of NonNull modifiers.
60- using TypeModifierStack = std::vector<service::TypeModifier>;
61-
62- // Scalar types are opaque to the generator, it's up to the service implementation
63- // to handle parsing, validating, and serializing them. We just need to track which
64- // scalar type names have been declared so we recognize the references.
65- struct ScalarType
66- {
67- std::string_view type;
68- std::string_view description;
69- };
70-
71- using ScalarTypeList = std::vector<ScalarType>;
72-
73- // Enum types map a type name to a collection of valid string values.
74- struct EnumValueType
75- {
76- std::string_view value;
77- std::string_view cppValue;
78- std::string_view description;
79- std::optional<std::string_view> deprecationReason;
80- std::optional<tao::graphqlpeg::position> position;
81- };
82-
83- struct EnumType
84- {
85- std::string_view type;
86- std::string_view cppType;
87- std::vector<EnumValueType> values;
88- std::string_view description;
89- };
90-
91- using EnumTypeList = std::vector<EnumType>;
92-
93- // Input types are complex types that have a set of named fields. Each field may be
94- // a scalar type (including lists or non-null wrappers) or another nested input type,
95- // but it cannot include output object types.
96- enum class InputFieldType
97- {
98- Builtin,
99- Scalar,
100- Enum,
101- Input,
102- };
103-
104- struct InputField
105- {
106- std::string_view type;
107- std::string_view name;
108- std::string_view cppName;
109- std::string_view defaultValueString;
110- response::Value defaultValue;
111- InputFieldType fieldType = InputFieldType::Builtin;
112- TypeModifierStack modifiers;
113- std::string_view description;
114- std::optional<tao::graphqlpeg::position> position;
115- };
116-
117- using InputFieldList = std::vector<InputField>;
118-
119- struct InputType
120- {
121- std::string_view type;
122- std::string_view cppType;
123- InputFieldList fields;
124- std::string_view description;
125- };
126-
127- using InputTypeList = std::vector<InputType>;
128-
129- // Directives are defined with arguments and a list of valid locations.
130- struct Directive
131- {
132- std::string_view name;
133- std::vector<std::string_view> locations;
134- InputFieldList arguments;
135- std::string_view description;
136- };
137-
138- using DirectiveList = std::vector<Directive>;
139-
140- // Union types map a type name to a set of potential concrete type names.
141- struct UnionType
142- {
143- std::string_view type;
144- std::string_view cppType;
145- std::vector<std::string_view> options;
146- std::string_view description;
147- };
148-
149- using UnionTypeList = std::vector<UnionType>;
150-
151- // Output types are scalar types or complex types that have a set of named fields. Each
152- // field may be a scalar type (including lists or non-null wrappers) or another nested
153- // output type, but it cannot include input object types. Each field can also take
154- // optional arguments which are all input types.
155- enum class OutputFieldType
156- {
157- Builtin,
158- Scalar,
159- Enum,
160- Union,
161- Interface,
162- Object,
163- };
164-
165- constexpr std::string_view strGet = " get" ;
166- constexpr std::string_view strApply = " apply" ;
167-
168- struct OutputField
169- {
170- std::string_view type;
171- std::string_view name;
172- std::string_view cppName;
173- InputFieldList arguments;
174- OutputFieldType fieldType = OutputFieldType::Builtin;
175- TypeModifierStack modifiers;
176- std::string_view description;
177- std::optional<std::string_view> deprecationReason;
178- std::optional<tao::graphqlpeg::position> position;
179- bool interfaceField = false ;
180- bool inheritedField = false ;
181- std::string_view accessor { strGet };
182- };
183-
184- using OutputFieldList = std::vector<OutputField>;
185-
186- // Interface types are abstract complex output types that have a set of fields. They
187- // are inherited by concrete object output types which support all of the fields in
188- // the interface, and the concrete object matches the interface for fragment type
189- // conditions. The fields can include any output type.
190- struct InterfaceType
191- {
192- std::string_view type;
193- std::string_view cppType;
194- OutputFieldList fields;
195- std::string_view description;
196- };
197-
198- using InterfaceTypeList = std::vector<InterfaceType>;
199-
200- // Object types are concrete complex output types that have a set of fields. They
201- // may inherit multiple interfaces.
202- struct ObjectType
203- {
204- std::string_view type;
205- std::string_view cppType;
206- std::vector<std::string_view> interfaces;
207- std::vector<std::string_view> unions;
208- OutputFieldList fields;
209- std::string_view description;
210- };
211-
212- using ObjectTypeList = std::vector<ObjectType>;
213-
214- // The client maps operation types to named types.
215- struct OperationType
216- {
217- std::string_view type;
218- std::string_view cppType;
219- std::string_view operation;
220- };
9+ #include " SchemaLoader.h"
22110
222- using OperationTypeList = std::vector<OperationType>;
11+ # include " graphqlservice/GraphQLSchema.h "
22312
224- struct GeneratorClient
225- {
226- const std::string schemaFilename;
227- const std::string requestFilename;
228- const std::string filenamePrefix;
229- const std::string clientNamespace;
230- };
13+ namespace graphql ::generator::client {
23114
23215struct GeneratorPaths
23316{
@@ -237,7 +20,7 @@ struct GeneratorPaths
23720
23821struct GeneratorOptions
23922{
240- const GeneratorClient client ;
23+ const std::string requestFilename ;
24124 const std::optional<GeneratorPaths> paths;
24225 const bool verbose = false ;
24326 const bool noIntrospection = false ;
@@ -247,7 +30,7 @@ class Generator
24730{
24831public:
24932 // Initialize the generator with the introspection client or a custom GraphQL client.
250- explicit Generator (GeneratorOptions&& options);
33+ explicit Generator (SchemaOptions&& schemaOptions, GeneratorOptions&& options);
25134
25235 // Run the generator and return a list of filenames that were output.
25336 std::vector<std::string> Build () const noexcept ;
@@ -258,82 +41,10 @@ class Generator
25841 std::string getHeaderPath () const noexcept ;
25942 std::string getSourcePath () const noexcept ;
26043
261- void visitDefinition (const peg::ast_node& definition);
262-
263- void visitClientDefinition (const peg::ast_node& clientDefinition);
264- void visitClientExtension (const peg::ast_node& clientExtension);
265- void visitScalarTypeDefinition (const peg::ast_node& scalarTypeDefinition);
266- void visitEnumTypeDefinition (const peg::ast_node& enumTypeDefinition);
267- void visitEnumTypeExtension (const peg::ast_node& enumTypeExtension);
268- void visitInputObjectTypeDefinition (const peg::ast_node& inputObjectTypeDefinition);
269- void visitInputObjectTypeExtension (const peg::ast_node& inputObjectTypeExtension);
270- void visitUnionTypeDefinition (const peg::ast_node& unionTypeDefinition);
271- void visitUnionTypeExtension (const peg::ast_node& unionTypeExtension);
272- void visitInterfaceTypeDefinition (const peg::ast_node& interfaceTypeDefinition);
273- void visitInterfaceTypeExtension (const peg::ast_node& interfaceTypeExtension);
274- void visitObjectTypeDefinition (const peg::ast_node& objectTypeDefinition);
275- void visitObjectTypeExtension (const peg::ast_node& objectTypeExtension);
276- void visitDirectiveDefinition (const peg::ast_node& directiveDefinition);
277-
278- static std::string_view getSafeCppName (std::string_view type) noexcept ;
279- static OutputFieldList getOutputFields (const peg::ast_node::children_t & fields);
280- static InputFieldList getInputFields (const peg::ast_node::children_t & fields);
281-
282- // Recursively visit a Type node until we reach a NamedType and we've
283- // taken stock of all of the modifier wrappers.
284- class TypeVisitor
285- {
286- public:
287- std::pair<std::string_view, TypeModifierStack> getType ();
288-
289- void visit (const peg::ast_node& typeName);
290-
291- private:
292- void visitNamedType (const peg::ast_node& namedType);
293- void visitListType (const peg::ast_node& listType);
294- void visitNonNullType (const peg::ast_node& nonNullType);
295-
296- std::string_view _type;
297- TypeModifierStack _modifiers;
298- bool _nonNull = false ;
299- };
300-
301- // Recursively visit a Value node representing the default value on an input field
302- // and build a JSON representation of the hardcoded value.
303- class DefaultValueVisitor
304- {
305- public:
306- response::Value getValue ();
307-
308- void visit (const peg::ast_node& value);
309-
310- private:
311- void visitIntValue (const peg::ast_node& intValue);
312- void visitFloatValue (const peg::ast_node& floatValue);
313- void visitStringValue (const peg::ast_node& stringValue);
314- void visitBooleanValue (const peg::ast_node& booleanValue);
315- void visitNullValue (const peg::ast_node& nullValue);
316- void visitEnumValue (const peg::ast_node& enumValue);
317- void visitListValue (const peg::ast_node& listValue);
318- void visitObjectValue (const peg::ast_node& objectValue);
319-
320- response::Value _value;
321- };
322-
323- void validateSchema ();
324- void fixupOutputFieldList (OutputFieldList& fields,
325- const std::optional<std::unordered_set<std::string_view>>& interfaceFields,
326- const std::optional<std::string_view>& accessor);
327- void fixupInputFieldList (InputFieldList& fields);
328-
32944 void validateQuery () const ;
33045 std::shared_ptr<schema::Schema> buildSchema () const ;
33146 void addTypesToSchema (const std::shared_ptr<schema::Schema>& schema) const ;
33247
333- std::string_view getCppType (std::string_view type) const noexcept ;
334- std::string getInputCppType (const InputField& field) const noexcept ;
335- std::string getOutputCppType (const OutputField& field) const noexcept ;
336-
33748 bool outputHeader () const noexcept ;
33849 void outputObjectDeclaration (
33950 std::ostream& headerFile, const ObjectType& objectType, bool isQueryType) const ;
@@ -356,39 +67,15 @@ class Generator
35667 const std::shared_ptr<schema::Schema>& schema, std::string_view type,
35768 TypeModifierStack modifiers, bool nonNull = true ) noexcept ;
35869
359- static const BuiltinTypeMap s_builtinTypes;
360- static const CppTypeMap s_builtinCppTypes;
361- static const std::string_view s_scalarCppType;
362- static const std::string s_currentDirectory;
363-
70+ SchemaLoader _loader;
36471 const GeneratorOptions _options;
365- std::string_view _clientNamespace;
36672 const std::string _headerDir;
36773 const std::string _sourceDir;
36874 const std::string _headerPath;
36975 const std::string _sourcePath;
370- peg::ast _schema;
37176 peg::ast _request;
372-
373- SchemaTypeMap _clientTypes;
374- PositionMap _typePositions;
375- TypeNameMap _scalarNames;
376- ScalarTypeList _scalarTypes;
377- TypeNameMap _enumNames;
378- EnumTypeList _enumTypes;
379- TypeNameMap _inputNames;
380- InputTypeList _inputTypes;
381- TypeNameMap _unionNames;
382- UnionTypeList _unionTypes;
383- TypeNameMap _interfaceNames;
384- InterfaceTypeList _interfaceTypes;
385- TypeNameMap _objectNames;
386- ObjectTypeList _objectTypes;
387- DirectiveList _directives;
388- PositionMap _directivePositions;
389- OperationTypeList _operationTypes;
39077};
39178
392- } /* namespace graphql::client */
79+ } /* namespace graphql::generator:: client */
39380
39481#endif // CLIENTGENERATOR_H
0 commit comments