diff --git a/src/HotChocolate/Core/src/Execution/Processing/MiddlewareContext.Pure.cs b/src/HotChocolate/Core/src/Execution/Processing/MiddlewareContext.Pure.cs index 742f8c5a576..85c8d9c2da7 100644 --- a/src/HotChocolate/Core/src/Execution/Processing/MiddlewareContext.Pure.cs +++ b/src/HotChocolate/Core/src/Execution/Processing/MiddlewareContext.Pure.cs @@ -66,7 +66,9 @@ public void Clear() public IObjectType ObjectType => _parentType; - public IFieldSelection Selection => _parentContext.Selection; + public IFieldSelection Selection => _selection; + + public Path Path => _path; public IVariableValueCollection Variables => _parentContext.Variables; diff --git a/src/HotChocolate/Core/src/Types/Resolvers/IPureResolverContext.cs b/src/HotChocolate/Core/src/Types/Resolvers/IPureResolverContext.cs index c31ef6366c1..eb99f6ebd9e 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/IPureResolverContext.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/IPureResolverContext.cs @@ -27,6 +27,11 @@ public interface IPureResolverContext : IHasContextData /// IObjectType ObjectType { get; } + /// + /// Gets the current execution path. + /// + Path Path { get; } + /// /// Gets the field selection for which a field resolver is /// being executed. diff --git a/src/HotChocolate/Core/src/Types/Resolvers/IResolverContext.cs b/src/HotChocolate/Core/src/Types/Resolvers/IResolverContext.cs index c1f2cbc9f7c..c8c6673c74e 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/IResolverContext.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/IResolverContext.cs @@ -50,11 +50,6 @@ public interface IResolverContext : IPureResolverContext /// NameString ResponseName { get; } - /// - /// Gets the current execution path. - /// - Path Path { get; } - /// /// Indicates that the context has errors. To report new errors use /// diff --git a/src/HotChocolate/Stitching/src/Stitching/Delegation/RemoteFieldHelper.cs b/src/HotChocolate/Stitching/src/Stitching/Delegation/RemoteFieldHelper.cs new file mode 100644 index 00000000000..d06fe6d9c03 --- /dev/null +++ b/src/HotChocolate/Stitching/src/Stitching/Delegation/RemoteFieldHelper.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using HotChocolate.Resolvers; +using HotChocolate.Types; + +namespace HotChocolate.Stitching.Delegation; + +internal static class RemoteFieldHelper +{ + public static object? RemoteFieldResolver(IPureResolverContext context) + { + if (!context.Selection.Field.Directives.Contains(DirectiveNames.Computed) && + context.Parent() is IReadOnlyDictionary dict) + { + var responseName = context.Selection.SyntaxNode.Alias == null + ? context.Selection.SyntaxNode.Name.Value + : context.Selection.SyntaxNode.Alias.Value; + + dict.TryGetValue(responseName, out var obj); + return DictionaryDeserializer.DeserializeResult( + context.Selection.Type, + obj, + context.Service(), + context.Path); + } + + return null; + } +} + diff --git a/src/HotChocolate/Stitching/src/Stitching/Utilities/StitchingTypeInterceptor.cs b/src/HotChocolate/Stitching/src/Stitching/Utilities/StitchingTypeInterceptor.cs index ccfa28b19c9..4bae757e35d 100644 --- a/src/HotChocolate/Stitching/src/Stitching/Utilities/StitchingTypeInterceptor.cs +++ b/src/HotChocolate/Stitching/src/Stitching/Utilities/StitchingTypeInterceptor.cs @@ -62,18 +62,15 @@ public override void OnBeforeCompleteType( { IReadOnlyDictionary> externalFieldLookup = completionContext.GetExternalFieldLookup(); - if (externalFieldLookup.TryGetValue( - objectType.Name, - out ISet? external)) + if (externalFieldLookup.TryGetValue(objectType.Name, out ISet? external)) { foreach (ObjectFieldDefinition objectField in objectTypeDef.Fields) { if (external.Contains(objectField.Name) && _handledExternalFields.Add((objectTypeDef.Name, objectField.Name))) { - FieldMiddleware handleDictionary = - FieldClassMiddlewareFactory.Create(); - objectField.MiddlewareDefinitions.Insert(0, new(handleDictionary)); + objectField.Resolvers = new FieldResolverDelegates( + pureResolver: RemoteFieldHelper.RemoteFieldResolver); } } } diff --git a/src/HotChocolate/Stitching/test/Stitching.Tests/Integration/FederatedSchemaTests.cs b/src/HotChocolate/Stitching/test/Stitching.Tests/Integration/FederatedSchemaTests.cs index 2ac59a1131f..5233131d188 100644 --- a/src/HotChocolate/Stitching/test/Stitching.Tests/Integration/FederatedSchemaTests.cs +++ b/src/HotChocolate/Stitching/test/Stitching.Tests/Integration/FederatedSchemaTests.cs @@ -14,6 +14,10 @@ using HotChocolate.Types; using Snapshooter.Xunit; using Xunit; +using HotChocolate.Execution.Processing; +using HotChocolate.Language; +using HotChocolate.Utilities; +using System.Linq; namespace HotChocolate.Stitching.Integration { @@ -126,6 +130,54 @@ public async Task AutoMerge_AddLocal_Field_Execute() result.ToJson().MatchSnapshot(); } + [Fact] + public async Task AutoMerge_CompileOperation() + { + // arrange + IHttpClientFactory httpClientFactory = CreateDefaultRemoteSchemas(); + + IRequestExecutor executor = + await new ServiceCollection() + .AddSingleton(httpClientFactory) + .AddGraphQL() + .AddQueryType(d => d.Name("Query").Field("local").Resolve("I am local.")) + .AddRemoteSchema(_accounts) + .AddRemoteSchema(_inventory) + .AddRemoteSchema(_products) + .AddRemoteSchema(_reviews) + .BuildRequestExecutorAsync(); + + DocumentNode document = Utf8GraphQLParser.Parse(@"{ + me { + id + name + reviews { + body + product { + upc + } + } + } + local + }"); + + OperationDefinitionNode operationDefinition = + document.Definitions.OfType().Single(); + + // act + IPreparedOperation operation = + OperationCompiler.Compile( + "a", + document, + operationDefinition, + executor.Schema, + executor.Schema.QueryType, + new(new DefaultTypeConverter())); + + // assert + operation.Print().MatchSnapshot(); + } + [Fact] public async Task Directive_Variables_Are_Correctly_Rewritten() { diff --git a/src/HotChocolate/Stitching/test/Stitching.Tests/Integration/__snapshots__/FederatedSchemaTests.AutoMerge_CompileOperation.snap b/src/HotChocolate/Stitching/test/Stitching.Tests/Integration/__snapshots__/FederatedSchemaTests.AutoMerge_CompileOperation.snap new file mode 100644 index 00000000000..9c573ceb115 --- /dev/null +++ b/src/HotChocolate/Stitching/test/Stitching.Tests/Integration/__snapshots__/FederatedSchemaTests.AutoMerge_CompileOperation.snap @@ -0,0 +1,21 @@ +{ + ... on Query { + me @__execute(id: 0, kind: DEFAULT, type: COMPOSITE) { + ... on User { + id @__execute(id: 2, kind: PURE, type: LEAF) + name @__execute(id: 3, kind: PURE, type: LEAF) + reviews @__execute(id: 4, kind: DEFAULT, type: COMPOSITE_LIST) { + ... on Review { + body @__execute(id: 5, kind: PURE, type: LEAF) + product @__execute(id: 6, kind: DEFAULT, type: COMPOSITE) { + ... on Product { + upc @__execute(id: 7, kind: PURE, type: LEAF) + } + } + } + } + } + } + local @__execute(id: 1, kind: DEFAULT, type: LEAF) + } +}