cppgraphqlgen icon indicating copy to clipboard operation
cppgraphqlgen copied to clipboard

Cannot use multiple client object in single compilation unit.

Open gitmodimo opened this issue 2 years ago • 4 comments

All clients uses the same include guard. If app uses multiple different queries multiple files generated by clientgen must be used. Since all of them use same guard we cannot include more than one at a time.

#ifndef GQLCLIENT_H
#define GQLCLIENT_H

gitmodimo avatar Jun 03 '22 13:06 gitmodimo

It's derived from the filename, which comes from the --prefix argument to clientgen. Since they're all the same, I'm assuming you are generating them in different directories. Rather than naming them all the same thing (Gql in this case), try naming them after whichever module/directory they're in. That will also disambiguate the filenames, so if all of those directories are in your include path, you won't need to specify the path prefix to determine which one is found when you include it.

wravery avatar Jun 03 '22 14:06 wravery

This is a little bit confusing. In order to use multiple clients in single compilation unit I have to:

  1. use unique --prefix to avoid include guard conflict
  2. use unique --namespace to avoid namespace conflict while accessing GetRequestObject()

gitmodimo avatar Jun 03 '22 15:06 gitmodimo

Yes, you do also need to disambiguate the namespace.

wravery avatar Jun 03 '22 15:06 wravery

I managed to get it up and running in my application. I can suggest few improvements that can be very useful.

  1. Wrap client functions in one object. Based on MutateClient example:
struct MutateClient{
[[nodiscard]] static const std::string& GetRequestText() noexcept;
[[nodiscard]] static const peg::ast& GetRequestObject() noexcept;
[[nodiscard]] static const std::string& GetOperationName() noexcept;
[[nodiscard]] static response::Value serializeVariables(Variables&& variables);
[[nodiscard]] static Response parseResponse(response::Value&& response);
}

Such class would allow to pass all functions related to single client into templates. Now it is not possible since those functions are only related by namespace.

template <typename MUTATION>
class MutationApi{
...
}
MutationApi<MutateClient> client;
client.do_something();
  1. It would be practical to use CompleteTaskInput and other input objects as they are defined in schema. In my application sometimes I have to forward graphql query to other node. If input types would be compatible it would be trivial task. Now I have to create deep copy of input objects one by one manually.
  2. Alternatively to 2.: CompleteTaskInput and other input object in client could have explicit template constructor(or factory function) that would be compatible with input objects as they defined in schema. It would not force clientgen user to include schema header, but it would allow interoperation.

gitmodimo avatar Jun 15 '22 21:06 gitmodimo