chkimes / graphql-net

Convert GraphQL to IQueryable

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Introspection and GraphiQL

gursharan001 opened this issue · comments

I see that README states introspection is incompleted.

With a asp.net graphiql project, i can run the queries on http://graphql.org/learn/introspection/ however Kind values in result are not right.

Also, the default graphiql query fails with an exception.

Will this be hard to do for someone new to the codebase?

Introspection is missing a few small things, but a large chunk of it is completed.

For incorrect Kind results, I think it would be reasonable for someone new to the codebase to find where the issue is. Search for usages of the TypeKind enumeration since there shouldn't be very many of them.

For the GraphiQL query failing, I'm not sure. It could be easy or difficult, depending on what exactly the query is. I should go get GraphiQL and spend some time getting it running with this library anyway, because it seems like a lot of people have adopted it.

Is there any advance here? I tried to add the missing parts the default graphiql query needs, like includeDeprecated, subscriptions and some others, but my knowledge of F# is close to 0. I could at least stop the query errors and get a response back but seems it wasn't well formed.

Instrospection would be great for bringing query validation and autocomplete in VSCode and other IDEs and generate static types in TypeScript based on queries and maybe C#. Among other benefits that takes advantage of GraphQL static typing.

commented

I'm looking for progress here too please ,
I think this is the most critical important issue for all of us ,
I can run my demo graphQL queries using console application , but it's not satisfaction enough,
something missing , we can't work and test 100% how we should ( yet )

I am currently trying to complete the implementation of introspections.

The "mapping" of CLR types (including inheritance) to the introspection types might be tricky. The GraphQL type system consists of:

  • Object type
  • Interface
  • Union type

Let's consider this data model:

    public class Character
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    public class Human : Character
    {
        public double Height { get; set; }
        public ICollection<Vehicle> Vehicles { get; set; }
    }
    public class Stormtrooper : Human
    {
        public string Specialization { get; set; }
    }

Assuming there is some root schema field called characters of type List<Character>, it should be possible to directly query the field id and use inline fragments with type conditions:

{
 characters {
    id
   ... on Human {
        Height
    }
 }
}

My understanding of the reference implementation of graphql for js is that the Character has to be an abstract introspection type, i.e. type kind INTERFACE or UNION to use type conditions.
An union type does not have own fields, so id could not be queried without a type condition.
An interface must have an implementing OBJECT type, so we would have to create an interface and an object type for Character.

These are the my first thoughts on this issue, maybe some of the above assumptions are incorrect.
Any ideas on this problems? @ckimes89

Unfortunately the GraphQL spec doesn't have a great story for inheritance hierarchies that exist in OOP languages like C# and Java. The best way to achieve the above is to generate the following types:

interface ICharacter {
    id
    name
}

object Character : ICharacter {
    id
    name
}

object Human : ICharacter {
    id
    name
    height
    vehicles
}

object StormTrooper : ICharacter {
    id
    name
    specialization
}

It's a bit disappointing, since there's the obvious problem of clashing with a real interface for ICharacter or dealing with multiple levels of inheritance. However, unless the GraphQL spec changes this is what we have to work with.

If GraphQL supported interfaces inheriting interfaces, we could get away with always just creating interfaces for base classes. There's no need to have a concrete object type if that type is only being queried.

However, as far as I know they only support one level of interface inheritance so this causes big problems with an inheritance hierarchy more than 2 levels deep.

What about making this more explicit so that the inheritance hierarchies are not reflected automatically, but have to be defined explicitly on the schema.
This might be possible by extending the schema API by methods addUnionType and addInterface and providing an overload for fields to specify the return type using an union type or interface.
By adding validation and proper error messages we could make this easy to use.

I know that extending the API might not be the best way, however this approach provides more flexibility.

What do you think @ckimes89?

@MarianPalkus I like the idea of explicitly requiring the user to opt-in to inheritance. All of the solutions for inheritance are pretty gross to handle automatically, especially as you get into deep inheritance hierarchies. I think it's best to let the user choose to explicitly say where inheritance should be used.

This would mean the default case for inherited types is duplication of some field definitions (e.g. Human defines its own id and name). However, I don't think this has a negative impact on the API since most people will likely just be calling AddAllFields.

The place where I would expect confusion is if a user expects the inheritance to be handled automatically, and then they get errors as they issue an invalid query. That error response is probably the best place to add an instructive error message to point the user to the fix.

Ok, thanks for your thoughts, i continue to implement it this way - may take a while.