graphql-platform icon indicating copy to clipboard operation
graphql-platform copied to clipboard

Stitching variables can't be referenced when a query requires an object parameter

Open ben-hth opened this issue 5 years ago • 15 comments

Describe the bug The documentation for schema stitching shows it's possible to reference resolver variables in the path using a special syntax.

extend type Query {
  me: User! @delegate(schema: "users", path: "user(id: $contextData:UserId)")
}

However when trying to access a resolver variable as an object property HotChocolate will throw a SyntaxException: 'Unexpexcted token: $.'

extend type Query {
  me: User! @delegate(schema: "users", path: "user(where: { id: $contextData:UserId })")
}

To Reproduce Modify the schema stitching example as above to reference a resolver variable within an object rather than a top level parameter and attempt to run the query.

Expected behavior The query should be parsed without an exception and the resolver variable should be included in the request.

Desktop (please complete the following information):

  • OS: Windows 10
  • Hot Chocolate 10.4.3 (also 11 preview 129)

Additional context Stepping through using the PDBs it looks like there would need to be a way to extend/inject the handling of $ variables from HotChocolate.Stitching.Delegation.SelectionPathParser.ParseValueLiteral in to HotChocolate.Parser.ParseValueLiteral as when Parser.ParseValueLiteral calls ParseObject it no longer calls through SelectionPathParser.ParseValueLiteral to have the chance to process stitching variables.

A hacky way to handle it could be to catch the Syntax Exception within SelectionPathParser.ParseValueLiteral and then re-attempt to handle the $ variable there.

ben-hth avatar May 13 '20 01:05 ben-hth

@PascalSenn didn't we fix that?

michaelstaib avatar May 13 '20 07:05 michaelstaib

@ben-hth thanks for reporting this.

michaelstaib avatar May 13 '20 07:05 michaelstaib

@michaelstaib i also thought that. apparently still not all cases

PascalSenn avatar May 14 '20 07:05 PascalSenn

There is a workaround for this that was posted in slack. Thanks @PascalSenn, hope my implementation is correct. 😄

Startup.cs

services
    .AddGraphQLServer()
    .MapField<ScopedContextMiddleware>(new FieldReference("Query", "me"))
    ...

ScopedContextMiddleware.cs

public class ScopedContextMiddleware
{
    private readonly FieldDelegate _next;
    public ScopedContextMiddleware(FieldDelegate next)
    {
        _next = next;
    }
    public async Task InvokeAsync(IMiddlewareContext context)
    {
        var filter = new Dictionary<string, object>();
        filter["id"] = context.ContextData["UserId"];
        context.ScopedContextData =
                context.ScopedContextData.SetItem("UserId", filter);
        await _next.Invoke(context);
    }
}

Stitching.graphql

extend type Query {
  me: User! @delegate(schema: "users", path: "user(where: $scopedContextData:UserId )")
}

KarlKl avatar Apr 28 '21 12:04 KarlKl

Has there been any additional findings with this issue? I'm experiencing the same thing, but not with the query, but when extending a type. Just wanted to check since this is a pretty important piece of functionality when stitching.

Example code below

extend type Request { PersonInformation: [PersonInformation] @delegate(schema: "employeeProfile", path: "personInformations(where: {id: {eq: $fields:employeeProfileId}})") }

Error: "extensions": { "message": "Unexpected token: $.", "stackTrace": " at HotChocolate.Language.Utf8GraphQLParser.ParseValueLiteral(Boolean isConstant)\r\n at HotChocolate.Language.Utf8GraphQLParser.ParseValueLiteral(Boolean isConstant)\r\n at HotChocolate.Language.Utf8GraphQLParser.ParseValueLiteral(Boolean isConstant)\r\n at HotChocolate.Stitching.SelectionPathParser.ParseValueLiteral(Utf8GraphQLParser& parser)\r\n at HotChocolate.Stitching.SelectionPathParser.ParseArgument(Utf8GraphQLParser& parser)\r\n at HotChocolate.Stitching.SelectionPathParser.ParseArguments(Utf8GraphQLParser& parser)\r\n at HotChocolate.Stitching.SelectionPathParser.ParseSelectionPathComponent(Utf8GraphQLParser& parser)\r\n at HotChocolate.Stitching.SelectionPathParser.ParseSelectionPath(Utf8GraphQLParser& parser)\r\n at HotChocolate.Stitching.SelectionPathParser.Parse(String path)\r\n at HotChocolate.Stitching.Utilities.FieldDependencyResolver.CollectFieldNames(DelegateDirective directive, IHasName type, ISet1 dependencies)\r\n at HotChocolate.Stitching.Utilities.FieldDependencyResolver.CollectDelegationDependencies(Context context, IHasName type, IOutputField field)\r\n at HotChocolate.Stitching.Utilities.FieldDependencyResolver.VisitField(FieldNode node, Context context)\r\n at HotChocolate.Language.SyntaxVisitor2.VisitSelection(ISelectionNode node, TContext context)\r\n at HotChocolate.Language.SyntaxVisitor2.VisitMany[T](IEnumerable1 items, TContext context, Action2 action)\r\n at HotChocolate.Language.QuerySyntaxWalker1.VisitSelectionSet(SelectionSetNode node, TContext context)\r\n at HotChocolate.Stitching.Utilities.FieldDependencyResolver.GetFieldDependencies(DocumentNode document, SelectionSetNode selectionSet, INamedOutputType declaringType)\r\n at HotChocolate.Stitching.Delegation.ExtractFieldQuerySyntaxRewriter.RewriteSelectionSet(SelectionSetNode node, Context context)\r\n at HotChocolate.Language.SyntaxRewriter1.Rewrite[TParent,TProperty](TParent parent, TProperty property, TContext context, Func3 visit, Func2 rewrite)\r\n at HotChocolate.Stitching.Delegation.ExtractFieldQuerySyntaxRewriter.RewriteFieldSelectionSet(FieldNode node, IOutputField field, Context context)\r\n at HotChocolate.Stitching.Delegation.ExtractFieldQuerySyntaxRewriter.RewriteField(FieldNode node, Context context)\r\n at HotChocolate.Stitching.Delegation.ExtractFieldQuerySyntaxRewriter.ExtractField(NameString sourceSchema, DocumentNode document, OperationDefinitionNode operation, IFieldSelection selection, INamedOutputType declaringType)\r\n at HotChocolate.Stitching.Delegation.DelegateToRemoteSchemaMiddleware.CreateQuery(IMiddlewareContext context, NameString schemaName, IImmutableStack1 path, IImmutableStack1 reversePath)\r\n at HotChocolate.Stitching.Delegation.DelegateToRemoteSchemaMiddleware.InvokeAsync(IMiddlewareContext context)\r\n at HotChocolate.Utilities.MiddlewareCompiler1.ExpressionHelper.AwaitTaskHelper(Task task)\r\n at HotChocolate.Execution.Processing.ResolverTask.ExecuteResolverPipelineAsync(CancellationToken cancellationToken)\r\n at HotChocolate.Execution.Processing.ResolverTask.TryExecuteAsync(CancellationToken cancellationToken)" }

bjswick33 avatar Aug 10 '21 17:08 bjswick33

This is unfortunately a deal breaker for me from using this library. I believe it is generally encouraged to use objects for query parameters for flexibility. In my case, for instance, I have:

public class Query
{
    public Order[] GetOrdersByUser(GetOrdersByUserInput input) { ... }
}

public record GetOrdersByUserInput(string userId, string orderType);

Then for my stitching:

extend type User {
    orders(type: String!): [Order] @delegate(path: "orderByUser(input: { userId: $fields:id orderType: $arguments:type })")
}

This seems reasonable to have. But that produces the error described.

abc-moviestarplanet avatar Nov 10 '21 13:11 abc-moviestarplanet

Rather disappointed there's no fix for this or no sign of one in any PRs or branches. Originally raised 18 months ago. It's definitely a deal-breaker as suggested above.

PBTests avatar Jan 10 '22 23:01 PBTests

@PBTests We are actively working on stitching and this limitation will be removed in v13

PascalSenn avatar Jan 10 '22 23:01 PascalSenn

Yes ... I hope that we have the first prototype end of next week. From that point forward we will have frequent previews. However, the first Gateway preview will not support everything we can today. This is a complete rewrite and brings many new features into the gateway with a much simpler setup. I will do a shoutout on slack to get feedback once we start with public testing.

michaelstaib avatar Jan 17 '22 15:01 michaelstaib

@michaelstaib I've tried the previews up until 15, but this one is not fixed yet. Any news about when a fix for this is scheduled?

ebjornset avatar Mar 09 '22 06:03 ebjornset

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar May 14 '22 10:05 stale[bot]

I may have just encountered this issue when using an array of primitives (int[] in this case)?

Using the following type extensions:

extend type User {
    roles: [Role] @delegate(schema: "roles", path: "roles(roleIds: $fields:roleIds)")
}

Where roleIds is an [int], trying to access this field results in:

"errors": [
	{
		"message": "Int cannot parse the given value of type `HotChocolate.Language.IntValueNode`."
	}
]

I've tried this with the latest preview (13.0.0-preview.19) too, same error.

jamiewinder avatar May 18 '22 21:05 jamiewinder

@jamiewinder can you share the type User ?

PascalSenn avatar May 19 '22 16:05 PascalSenn

@PascalSenn Sure thing, it's simply:

type User {
   userId: Int!
   name: String!
   roleIds: [Int!]!
}

And, if helpful, this is the roles query operation referred to in the delegate:

type Query {
  roles(roleIds: [Int!]!): [Role!]!
}

Thanks.

jamiewinder avatar May 19 '22 16:05 jamiewinder

@jamiewinder did you ever resolve this? I'm facing the same issue with an array of Guids.

heymanitsmematt avatar Sep 22 '22 01:09 heymanitsmematt

@heymanitsmematt afraid not!

jamiewinder avatar Sep 22 '22 14:09 jamiewinder

This is fixed with the new gateway of 13

michaelstaib avatar Sep 22 '22 14:09 michaelstaib

We have moved this to 13.1 with the new gateway version.

michaelstaib avatar Dec 20 '22 08:12 michaelstaib

Any ETA on this? I'm using 13.0.0-rc1, but problem still exists in that version..

jochemvankessel avatar Jan 23 '23 10:01 jochemvankessel

HotChocolate.Stitching is now in legacy mode and is replaced by HotChocolate.Fusion. I am closing this issue as we essentially froze the fusion code.

michaelstaib avatar Mar 08 '23 20:03 michaelstaib

You can join the beta for fusion no on slack.

michaelstaib avatar Mar 08 '23 20:03 michaelstaib