graphql-zeus
graphql-zeus copied to clipboard
Parsed schema is broken
I'm evaluating possibilities and options to interact with an existing GraphQL API that is provided by a CMS called Statamic Pro.
On running zeus with this npm command: zeus https://someurl.com/graphql ./ --ts
the contents of the output const.ts are broken in several places:
// … other parts of the file
export const ReturnTypes: Record<string,any> = {
// … non-broken lines
GlobalSetInterface:{
,
handle:"String",
site:"Site",
title:"String"
},
PageInterface:{
,
entry_id:"ID",
id:"ID",
permalink:"String",
title:"String",
url:"String"
},
TermInterface:{
,
edit_url:"String",
id:"ID",
permalink:"String",
slug:"String",
taxonomy:"Taxonomy",
title:"String",
uri:"String",
url:"String"
},
// … non-broken lines
}
the corresponding parts of the schema look like this:
…
interface GlobalSetInterface {
handle: String!
site: Site!
title: String!
}
interface PageInterface {
entry_id: ID
id: ID!
permalink: String
title: String
url: String
}
interface TermInterface {
edit_url: String!
id: ID!
permalink: String
slug: String!
taxonomy: Taxonomy!
title: String!
uri: String
url: String
}
…
This also leads to a broken index.ts file:
export type ModelTypes = {
["AssetInterface"]: ModelTypes["Asset_Assets"] | ModelTypes["Asset_Images"];
["EntryInterface"]: ModelTypes["Entry_Articles_Articles"] | ModelTypes["Entry_Authors_Authors"] | ModelTypes["Entry_Issues_Issues"];
["GlobalSetInterface"]: ;
["PageInterface"]: ;
["TermInterface"]: ;
["Sets_Content"]:ModelTypes["BardText"] | ModelTypes["Set_Content_Vimeo"];
["AssetContainer"]: {
handle:string,
title:string
};
I'm running Node v16.9.1, typescript 4.4.3. The entire schema is available here: https://www.codepile.net/pile/vl0p0Zl0 The output of const.ts: https://www.codepile.net/pile/N43knP4a The output of index.ts: https://www.codepile.net/pile/PKzP408j
I'm happy to provide more info to assist in debugging this. I'd love to use zeus, it looks great.
Hi! I can fix this but you should not be able to use the schema either. You have interfaces that are left unused, so if the query returns interface that is not implemented anywhere, it is hard to generate correct typings. I do not know what tool you are using but the schema it's generating is against the spec and incorrect.
As a workaround we can add __typename: never
to those incorrect interfaces so they don't break the code generation
@grischaerbe
@aexol Thanks for your effort & the clarification that the schema is against the spec, I was already suspecting that. The schema is generated automatically based on the setup of the CMS, the underlying library that is handling the heavy lifting of providing the GraphQL API – including the schema – is https://github.com/rebing/graphql-laravel. I'm not that much into the spec of GraphQL schemas but if I understand you correctly unused interfaces (like DateRange) are not allowed? Is that related to the broken code generation? Maybe it's a good idea to strip out these unused types beforehand.
Fixed in 3.1.9, but I still don't know what you can do with it.
@grischaerbe
It means that when you return an interface, you return one of types implementing the interface. If no types are present then the resolver should not return anything
Thanks again for your effort and the quick fix @aexol.
I'm not sure if I understand you correctly. Is it that the schema contains types that are not implemented anywhere or that the ReturnType includes type names that don't have types?
I can see that with 3.1.9 the type GlobalSetInterface
includes a __typename:never
(so I guess by that it's being marked as unused?) but it is actually the ReturnType of the queries globalSet
and globalSets
.
Interface is only valid when implemented by types
So when interface Animal
is implemented by Cat
Pig
Dog
it's __typename
is __typename: "Cat" | "Pig" | "Dog"
Ah, i see. So e.g. the interface GlobalSetInterface
has not been implemented by any type
but is marked as the return type of the query globalSets
which renders the schema as against the GQL spec. Got it! I'll report back to the Statamic people. Thanks a ton, learned something today!
Interface is only valid when implemented by types
Is this in the spec? Where?
The interface type should have some way of determining which object a given result corresponds to. Once it has done so, the result coercion of the interface is the same as the result coercion of the object.
@jasonvarga btw we are talking about __typename
generated I think I can find the solution that will satisfy both worlds and allow for interface to be returned with __typename: "InterfaceNameHere"
if that will help @grischaerbe I can make that change as I don't care how invalid interface ar transformed. What do you both think?
@jasonvarga @grischaerbe
Sorry I'm not familiar with this package or typescript but that sounds good to me.