byme8 / ZeroQL

C# GraphQL client with Linq-like syntax
MIT License
278 stars 13 forks source link

FailedToConvertPartOfTheQuery: Failed to convert to graphql query: i #37

Closed JuanuMusic closed 1 year ago

JuanuMusic commented 1 year ago

Describe the bug When executing a Query or Mutation with variables, the project won't compile with the error FailedToConvertPartOfTheQuery

How to Reproduce

Create new project with the graphql schema url: https://api-mumbai.lens.dev/graphql/:

Project init:

dotnet new console -o QLClient
cd QLClient
dotnet new tool-manifest 
dotnet tool install ZeroQL.CLI
dotnet add package ZeroQL 
dotnet zeroql schema pull -u https://api-mumbai.lens.dev/graphql/
dotnet zeroql generate --schema ./schema.graphql --namespace TestServer.Client --client-name TestServerGraphQLClient --output Generated/GraphQL.g.cs

Program.cs:

using TestServer.Client;

var httpClient = new HttpClient();
httpClient.BaseAddress = new Uri("https://api-mumbai.lens.dev/graphql/");
var client = new TestServerGraphQLClient(httpClient);

var request = new ChallengeRequest { Address = "0x1c2eAdbB291709D3252610C431A6Ee355191E545" };
client.Query(request, static (i, o) => o.Challenge(i, result => new { result.Text }));

Expected behavior The project should compile and run the queries.

Screenshots image

Environment (please complete the following information):

byme8 commented 1 year ago

The next sample should work:

using TestServer.Client;

var httpClient = new HttpClient();
httpClient.BaseAddress = new Uri("https://api-mumbai.lens.dev/graphql/");
var client = new TestServerGraphQLClient(httpClient);

var variables = new { Input = new ChallengeRequest { Address = "0x1c2eAdbB291709D3252610C431A6Ee355191E545" } };
client.Query(variables, static (i, o) => o.Challenge(i.Input, result => new { result.Text }));

At the moment, it is the limitation of the current approach. The object properties as directly mapped into GraphQL variables. So, if you want to pass a single object to have to make a wrapper around it.

byme8 commented 1 year ago

I think I have to add a custom error message for such cases to avoid future misunderstanding,

JuanuMusic commented 1 year ago

Ok, I think i have a similar issue with a lower level function. I'm trying to replicate this query:

fragment ProfileStats on ProfileStats {
  __typename
  totalCollects
  totalComments
  totalFollowers
  totalFollowing
  totalMirrors
  totalPosts
  totalPublications

  commentsTotal(forSources: $sources)
  postsTotal(forSources: $sources)
  mirrorsTotal(forSources: $sources)
  publicationsTotal(forSources: $sources)
}

query ProfileStats($request: SingleProfileQueryRequest!, $sources: [Sources!]!) {
  result: profile(request: $request) {
    stats {
      ...ProfileStats
    }
  }
}

With this code:

// See https://aka.ms/new-console-template for more information
using TestServer.Client;
using ZeroQL;

public record ProfileStatsFragment
{
    public int TotalCollects { get; set; }
    public int TotalComments { get; set; }
    public int TotalFollowers { get; set; }
    public int TotalFollowing { get; set; }
    public int TotalMirrors { get; set; }
    public int TotalPosts { get; set; }
    public int TotalPublications { get; set; }
    public int CommentsTotal { get; internal set; }
    public int PostsTotal { get; internal set; }
    public int MirrorsTotal { get; internal set; }
    public int PublicationsTotal { get; internal set; }

    //   commentsTotal(forSources: $sources)
    //postsTotal(forSources: $sources)
    //mirrorsTotal(forSources: $sources)
    //publicationsTotal(forSources: $sources)
}

public static class FragmentsExtensions {
    [GraphQLFragment]
    public static ProfileStatsFragment AsProfileStatsFragment(this ProfileStats profileStats, Sources[] sources)
    {
        return new ProfileStatsFragment
        {
            TotalComments = profileStats.TotalComments,
            TotalCollects = profileStats.TotalCollects,
            TotalFollowers = profileStats.TotalFollowers,
            TotalFollowing = profileStats.TotalFollowing,
            TotalMirrors = profileStats.TotalMirrors,
            TotalPosts = profileStats.TotalPosts,
            TotalPublications = profileStats.TotalPublications,
            //CommentsTotal = profileStats.CommentsTotal(sources),
            //PostsTotal = profileStats.PostsTotal(sources),
            //MirrorsTotal = profileStats.MirrorsTotal(sources),
            //PublicationsTotal = profileStats.PublicationsTotal(sources)
        };
    }
};

public static class Program {

    public static async void Main(string[] args) {

        var httpClient = new HttpClient();
        httpClient.BaseAddress = new Uri("https://api-mumbai.lens.dev/graphql/");
        var client = new TestServerGraphQLClient(httpClient);

        var request = new {
            Input = new SingleProfileQueryRequest { ProfileId = "0x0185" },
            Sources = new Sources[] { new Sources("lenster") }
        };

        var stats = client.Query(request,
            static (i, o)
                => o.Profile(i.Input, result
                    => new { r = result.Stats(static (outStats)
                        => new ProfileStats { Id = outStats.Id, TotalCollects = outStats.TotalCollects } }));

    }
}

But getting this: image

I am using the Sources property as sibbling to the Input, not sure if its correct.

byme8 commented 1 year ago

There is no need for second static.

var request = new {
    Input = new SingleProfileQueryRequest { ProfileId = "0x0185" },
    Sources = new Sources[] { new Sources("lenster") }
};

var stats = client.Query(request,
    static (i, o)
        => o.Profile(i.Input, result
            => new { r = result.Stats(outStats
                => new 
                {
                    Id = outStats.Id,
                    TotalCollects = outStats.TotalCollects,
                    TotalCollectsValue = outStats.CommentsTotal(i.Sources),
                })}));
JuanuMusic commented 1 year ago

Ohh I see! Thanks!