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

Removing all mutations from subgraphs doesn't remove the Mutation type from the supergraph schema

Open scottstubbs opened this issue 1 year ago • 6 comments

Product

Hot Chocolate

Version

14.2.0

Link to minimal reproduction

https://github.com/scottstubbs/HotChocolate-Fusion-Hide-Mutations

Steps to reproduce

To run the solution:

  1. Run dotnet tool restore
  2. Build HotChocolate-Fusion-Mutations.sln
  3. Run all projects (Gateway, Owners and Cars) in the solution
  4. Open https://localhost:50000/graphql in a browser
  5. Create a new document in Nitro

At this point the introspection fails.

To make changes to the subgraphs, rebuild the gateway from the root directory:

  • Run ./Fuse.ps1 to pack and compose all projects OR
  • Run ./Fuse.ps1 -Project {ProjectFolder} to pack and compose a specific project

What is expected?

Introspection should succeed. The Mutation type should be gone from the supergraph schema.

What is actually happening?

Introspection fails and the error is logged to the Nitro console and the Visual Studio Output window.

Relevant log output

info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:50000
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: C:\users\sstubbs\source\repos\ReadOnly\Gateway
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
      An unhandled exception has occurred while executing the request.
      HotChocolate.SchemaException: For more details look at the `Errors` property.

      1. The object type `Mutation` has to at least define one field in order to be valid. (HotChocolate.Types.ObjectType)

         at HotChocolate.SchemaBuilder.Setup.CompleteSchema(SchemaBuilder builder, IDescriptorContext context, LazySchema lazySchema, TypeRegistry typeRegistry)
         at HotChocolate.SchemaBuilder.Setup.Create(SchemaBuilder builder, LazySchema lazySchema, IDescriptorContext context)
         at HotChocolate.SchemaBuilder.Create(IDescriptorContext context)
         at HotChocolate.SchemaBuilder.HotChocolate.ISchemaBuilder.Create(IDescriptorContext context)
         at HotChocolate.Execution.RequestExecutorResolver.CreateSchemaAsync(ConfigurationContext context, RequestExecutorSetup setup, RequestExecutorOptions executorOptions, IServiceProvider schemaServices, TypeModuleChangeMonitor typeModuleChangeMonitor, CancellationToken cancellationToken)
         at HotChocolate.Execution.RequestExecutorResolver.CreateSchemaServicesAsync(ConfigurationContext context, RequestExecutorSetup setup, CancellationToken cancellationToken)
         at HotChocolate.Execution.RequestExecutorResolver.GetRequestExecutorNoLockAsync(String schemaName, CancellationToken cancellationToken)
         at HotChocolate.Execution.RequestExecutorResolver.GetRequestExecutorAsync(String schemaName, CancellationToken cancellationToken)
         at HotChocolate.Execution.RequestExecutorProxy.GetRequestExecutorAsync(CancellationToken cancellationToken)
         at HotChocolate.AspNetCore.HttpGetSchemaMiddleware.HandleRequestAsync(HttpContext context)
         at HotChocolate.AspNetCore.HttpGetSchemaMiddleware.InvokeAsync(HttpContext context)
         at HotChocolate.AspNetCore.HttpGetMiddleware.InvokeAsync(HttpContext context)
         at HotChocolate.AspNetCore.HttpMultipartMiddleware.InvokeAsync(HttpContext context)
         at HotChocolate.AspNetCore.HttpPostMiddlewareBase.InvokeAsync(HttpContext context)
         at Microsoft.AspNetCore.Builder.EndpointRouteBuilderExtensions.<>c__DisplayClass23_0.<<UseCancellation>b__1>d.MoveNext()
      --- End of stack trace from previous location ---
         at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

Additional context

This happens because all subgraph mutations were marked with the [Internal] attribute. The fusion compose command doesn't remove the empty Mutation type from the supergraph schema. The same result happens when using the [Tag(name: "internal")] attribute.

scottstubbs avatar Dec 09 '24 12:12 scottstubbs

It would be nice to have something like the [Inaccessible] attribute from the HotChocolate.ApolloFederation.Types to remove an entire Mutation type from subgraphs instead of individually marking all mutations as [Internal].

scottstubbs avatar Dec 09 '24 12:12 scottstubbs

@scottstubbs this is coming with the March release.

michaelstaib avatar Dec 10 '24 13:12 michaelstaib

At the moment you can use the @remove directive to remove the type. it allows to remove type system members. Simply create an schema.extensions.graphql and annotate it to the schema like the following:

extend schema 
    @remove(coordinate: "Mutation") 
{
}

With the march release we will have @inaccessible you can have a look at what directives are coming with the march release here: https://github.com/graphql/composite-schemas-spec/blob/main/spec/Section%202%20--%20Source%20Schema.md

michaelstaib avatar Dec 10 '24 14:12 michaelstaib

Thank you for the guidance. After adding the schema.extensions.graphql file to the Owners and Cars projects, I get the same error. It appears that the compose step still doesn't remove the Mutation type. Maybe I didn't set the files up right or maybe I'm running the fusion commands incorrectly in my Fuse.ps1 script? The repo is up to date with my schema extension changes for review.

scottstubbs avatar Dec 10 '24 16:12 scottstubbs

I will have a look at it.

michaelstaib avatar Dec 12 '24 12:12 michaelstaib

Updated the repo to the latest version 15.1.3, and continue to see the error when Hot Chocolate tries to build the schema with an empty Mutation type.

scottstubbs avatar Apr 08 '25 13:04 scottstubbs