ChilliCream / graphql-platform

Welcome to the home of the Hot Chocolate GraphQL server for .NET, the Strawberry Shake GraphQL client for .NET and Banana Cake Pop the awesome Monaco based GraphQL IDE.
https://chillicream.com
MIT License
5.14k stars 736 forks source link

Support for returning Edge types in Mutations for Relay-style connections #7411

Open noricube opened 2 weeks ago

noricube commented 2 weeks ago

Product

Hot Chocolate

Is your feature request related to a problem?

Background

In Relay, there are directives like appendEdge and prependEdge that allow direct insertion of results into a connection. For example, as documented in the Relay documentation, you can easily append or prepend edges to existing connections in mutations.

Current Situation

In Hot Chocolate GraphQL, when using UsePaging for queries, it correctly returns Edge and Node types. However, for mutations, there doesn't seem to be a built-in way to transform and return data in the Edge format.

Question / Feature Request

Is there a recommended approach or existing feature in Hot Chocolate GraphQL for returning Edge types in mutations when working with Relay-style connections? If not, would it be possible to add support for this? This feature would be particularly useful for maintaining consistency between query and mutation interfaces, especially when working with paginated data or implementing real-time updates to lists.

Any insights or suggestions on how to handle this scenario would be greatly appreciated. Thank you for your time and consideration!

The solution you'd like

I would like to see an attribute or utility function that allows mutation return types to be easily converted to Edge types. Specifically:

An attribute that can be applied to mutation methods, similar to [UsePaging] for queries, but for mutations. For example:

[UseEdgeReturn]
public async Task<FooPayload> AddFooMutation(AddFooInput input)
{
    // Implementation
}

This attribute would automatically wrap the return value in an Edge type.

A utility function that can be used within mutation resolvers to convert a return value to an Edge type. For example:

public async Task<FooEdge> AddFooMutation(AddFooInput input)
{
    var foo = await _fooService.AddFoo(input);
    return foo.ToEdge(); // Utility extension method
}

Either of these solutions would greatly simplify the process of returning Edge types from mutations, maintaining consistency with the Relay specification and making it easier to work with connections in a Relay-compatible way.

michaelstaib commented 2 weeks ago

We have this on the internal backlog. What you can do at the moment is use appendNode instead. However, we probably will add this for Hot Chocolate 14.1.

We are at the moment researching a bit how to deal with user controlled ordering and how this order structure would be a transitive state in a mutation.

API wise we would have something like this:

public async Task<IEdge<Foo>> AddFooMutation(AddFooInput input, IUserControlledOrder order)
{
    var foo = await _fooService.AddFoo(input);
    return Edge.From(foo, order);
}

or when having a fixed order

public async Task<IEdge<Foo>> AddFooMutation(AddFooInput input)
{
    var foo = await _fooService.AddFoo(input);
    return Edge.From(foo, t => new { t.Name, t.Id });
}

Since order is important here the selector might be different. could also be:

return Edge.From(foo, q => q.OrderBy(t => t.Name).ThenBy(t => t.Id));

As said ... this are all experimentations.

noricube commented 2 weeks ago

Thank you for the information and clarification. I appreciate your team's effort in working on this feature. I'm looking forward to the release of Hot Chocolate 14.1 with these new capabilities. In the meantime, I'll use the appendNode approach as you suggested.

Thanks again for your help.