How can I print the schema in HotChocolate as GraphQL SDL
Asked Answered
M

3

14

It would be great for development with Relay to print the GraphQL SDL directly with the Hot Chocolate GraphQL server. Is there a way to do this?

schema {
  query: Query
}

type Query {
  sayHello: String
}
Messing answered 14/1, 2021 at 10:44 Comment(0)
M
22

Hot Chocolate Server provides easy ways to print the schema as GraphQL SDL.

  1. You can print any schema by calling ToString on ISchema.

    This is a more programmatic way to do it, but never the less it can be quite useful to just print the schema in tests or console tools. Good to know here is that any syntax node will allow you to be printed that way. So, even if you want to print a parsed query, you can just do ToString on it to get its GraphQL language string representation.

  2. For things like Relay, it is quite useful to have the schema available on an endpoint to just download it. Hot Chocolate server provides in all versions a GraphQL SDL endpoint.

    Version 10 and earlier: http://localhost:5000/graphql/schema

    Version 11 and newer: http://localhost:5000/graphql?sdl

    This URL should be valid when hosting the GraphQL endpoint on the graphql route.

Messing answered 14/1, 2021 at 10:44 Comment(3)
Does hotchocolate provide a built-in means to extract the SDL without running the server?Gobo
Would be useful for CI/CD systems to be able to get this at build time without running the server.. though maybe thats just my dinosaur brainGrannias
With HC 13, where do you get ISchema from?Grannias
I
5

If you want to generate the schema in CI/CD, you can add a CLI argument that generates the schema and doesn't start the app. Something like:

In Program.cs:

if (args.Any(c => c == "--generate-schema"))
{
  builder.Services.AddGraphQL().InitializeOnStartup();
  var app = builder.Build();
  var executor = host.Services.GetRequiredService<IRequestExecutorResolver>().GetRequestExecutorAsync().Result;
  var schema = executor.Schema.Print();
  File.WriteAllText("schema.graphql", schema);
  return;
}
Instance answered 28/4, 2022 at 9:43 Comment(1)
Should that read var executor = app.Services... instead of host.Services?Jo
L
4

If you are using code first with attributes to automatically generate your schema, here is an example of how to get an instance of the schema and write it to a file if it has changed.

I placed this code in Program.cs so it auto-generates my schema.graphql file for my front end tooling when my aspnet.core project starts during development.

HostInstance = builder.Build();
if(Debugger.IsAttached)
{
    var resolver = HostInstance.Services.GetService<IRequestExecutorResolver>();
    if (resolver != null)
    {
        var executor = resolver.GetRequestExecutorAsync().Result;
        if (executor != null)
        {
            var schemaFile = Path.Combine(ProjectPathInfo.ProjectPath, "Apps\\src\\lib\\com\\GraphQL\\schema.graphql");
            var newSchema = executor.Schema.ToString();
            var oldSchema = File.ReadAllText(schemaFile);
            if (newSchema != oldSchema)
                File.WriteAllText(schemaFile, newSchema);
        }
    }

}

I use this supporting internal class (borrowed from here) to find the project folder to use for the output of the SDL.

internal static class ProjectPathInfo
{
    public static string CSharpClassFileName = nameof(ProjectPathInfo) + ".cs";
    public static string CSharpClassPath;
    public static string ProjectPath;
    public static string SolutionPath;

    static ProjectPathInfo()
    {
        CSharpClassPath = GetSourceFilePathName();
        ProjectPath = Directory.GetParent(CSharpClassPath)!.FullName;
        SolutionPath = Directory.GetParent(ProjectPath)!.FullName;
    }

    private static string GetSourceFilePathName([CallerFilePath] string callerFilePath = null) => callerFilePath ?? "";
}
Lee answered 15/12, 2021 at 19:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.