Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[question] How do I extend a base graph type #1120

Closed
pingvinen opened this issue Oct 10, 2019 · 6 comments
Closed

[question] How do I extend a base graph type #1120

pingvinen opened this issue Oct 10, 2019 · 6 comments
Assignees
Labels
❓ question This issue is a question about feature of Hot Chocolate.
Milestone

Comments

@pingvinen
Copy link

Hi

I have a situation where I would like to expose a clean graph for consumers (at /graphql) of my service and a bigger graph for my back-office system (at /private_graphql).

I am using the HotChocolate 10.1.0 package.

This is what I am trying to achieve

A shared base type for a User

User
  id
  name

A public version of User

User
  id (from base)
  name (from base)
  relationToMe (public only)

A private version of User

User
  id (from base)
  name (from base)
  forAdminEyesOnly (private only)

How do I do this? Is it even possible?

I have tried a bunch of different ways to achieve this, but have so far failed :(

I have tried using the .Extend() stuff, but I never seem to actually have anyting in the descriptor to work with.

I looked into using a Directive, but I failed to identify how to remove a field in the InvokeAsync implementation.

I am considering using stitching within my service, where I build a shared schema, a public schema and a private schema, and then serve a stiched schema with the shared and the public or private schema.

Also of note

I am using ServiceStack instead of AspNetCore MVC and building the schema using the following code:

var builder = SchemaBuilder
    .New()
    .AddServices(_container)
    .AddQueryType<TQuery>();

I am aware that this concept is being discussed in lots of different forums all over the internet and has been for years. I have already built other graphs where fields are simply nulled if the user does not have the proper permissions etc.

Please do not turn this question into a discussion of 1 vs n graphs. Thank you :)

@michaelstaib michaelstaib added the ❓ question This issue is a question about feature of Hot Chocolate. label Oct 10, 2019
@michaelstaib michaelstaib self-assigned this Oct 10, 2019
@michaelstaib
Copy link
Member

Hi,

it is possible with extensions. You basically have to SchemaBuilder instances and add the extension types that are specific to a schema to the corresponding type.

var privateSchema = SchemaBuilder
    .New()
    .AddServices(_container)
    .AddQueryType<SharedQueryType>()
    .AddType<PrivateQueryTypeExtension>()
    .Build()
var publicSchema = SchemaBuilder
    .New()
    .AddServices(_container)
    .AddQueryType<SharedQueryType>()
    .AddType<PublicQueryTypeExtension>()
    .Build()

https://hotchocolate.io/docs/schema-object-type#extension

In the shared schema you can also use classes to import resolvers like the following:

public class PersonTypeExtension
    : ObjectTypeExtension
{
    protected override Configure(IObjectTypeDescriptor descriptor)
    {
        descriptor.Name("Person");
        descriptor.Field<FooClass>(t => t.Bar)
            .Type<NonNullType<StringType>>();
    }
}

It is important to know that the type is matched by its name. So, the type extension and its type has to have the same name.

This is also working with sdl-first approach, in the sdl-first approach you would do:

extend type Foo {
    custom: String
} 

Please do not turn this question into a discussion of 1 vs n graphs. Thank you :)

We are not opinionated.

Does this help you?

@michaelstaib michaelstaib added this to the 10.2.0 milestone Oct 10, 2019
@michaelstaib
Copy link
Member

Also we have a very active slack channel which is great for discussing things like this. So feel free to join... the link is on our readme.

@pingvinen
Copy link
Author

I made a minimal-ish solution to show the full scope of everything: https://github.com/pingvinen/hotchocolate-issue-1120

Does this help you?

Yes. It pointed me in the right direction, but I think the documentation could use some examples like this. The current documentation on "extending types" does not contain any examples and pointed me in the direction of the descriptor.Name(..).Extend().On* methods. I used the debugger to look at the things available to me and everything was just empty.

I ended with something like this.

public class PrivateUserGraphTypeExtension : ObjectTypeExtension
{
  protected override void Configure(IObjectTypeDescriptor descriptor)
  {
    descriptor.Name(UserGraphType.GraphName);
    descriptor.Field<UserGqlOut>(t => t.ForAdminEyesOnly);
  }
}

...and...

schemaBuilder.AddType<PrivateUserGraphTypeExtension>();

Thank you very much for your extremely fast response @michaelstaib

@michaelstaib
Copy link
Member

Just as a side note:

https://github.com/pingvinen/hotchocolate-issue-1120/blob/e1f91d15a40cd3e9703bdd07cc7327b638f4e8a5/GraphStuff/Endpoint/GraphQlService.cs#L26

Building the schema is expensive ... so make sure that you store the schema somewhere and do not build it on every request.

@michaelstaib
Copy link
Member

descriptor.Name(..).Extend().On*

Extend() is meant for extensions like providing a entity framework extension or a paging extension etc.

I will add some more documentation.

@pingvinen
Copy link
Author

Building the schema is expensive ... so make sure that you store the schema somewhere and do not build it on every request.

Thank you. This actual codebase is 2 days old at the moment, so it is still early days :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
❓ question This issue is a question about feature of Hot Chocolate.
Projects
None yet
Development

No branches or pull requests

2 participants