gatsby-source-sanity
gatsby-source-sanity copied to clipboard
Root object schema does not implement the Gatsby Node interface
Hi.
I'm chasing down an error that's being thrown by Gatsby during the build process. Apologies in advance in case some of my assumptions below are wrong, but here goes:
info [sanity] Fetching remote GraphQL schema
info [sanity] Transforming to Gatsby-compatible GraphQL SDL
info [sanity] Stitching GraphQL schemas from SDL
success onPreBootstrap — 0.236 s
info [sanity] Fetching export stream for dataset
info [sanity] Watch mode enabled, starting a listener
info [sanity] Done exporting!
success source and transform nodes — 0.664 s
warning Type `SanityArticle` declared in `createTypes` looks like a node, but doesn't implement a `Node` interface. It's likely that you should add the `Node` interface to your type def:
`type SanityArticle implements Node { ... }`
If you know that you don't want it to be a node (which would mean no root queries to retrieve it), you can explicitly disable inference for it:
`type SanityArticle @dontInfer { ... }`
error Building schema failed
error Command failed with exit code 1.
It seams like an error gets thrown because I have defined an Article
model of type object
(instead of document
), but I have included this model as a "root schema" in the sanity schema configuration:
// schemas/schema.js
export default createSchema({
name: "default",
types: schemaTypes.concat([
article: {
type: "object",
name: "article",
title: "Article",
fields: [
{
type: "string",
name: "title",
title: "Title"
},
{
type: "string",
name: "content",
title: "Content"
}
]
},
page: {
type: "document",
name: "page",
title: "Page",
fields: [
{
type: "string",
name: "title",
title: "Title"
},
{
type: "article",
name: "article",
title: "Article"
}
]
}
])
})
While debugging, I'm seeing that the schema SDL that gets generated here becomes something something like this:
type SanityArticle {
_key: String
_type: String
title: String
content: String
}
type SanityPage implements SanityDocument & Node {
_id: String
_type: String
_createdAt: Date
_updatedAt: Date
_rev: String
_key: String
title: String
article: SanityArticle
}
"""
A Sanity document
"""
interface SanityDocument {
_id: String
_type: String
_createdAt: Date
_updatedAt: Date
_rev: String
}
Which is why we see the error above. From here, we can test the two different suggestions from the error message:
Implement the Node interface:
I attempted to remove this check, this resulted in a successful build/develop, and I could query the data like this:
query {
allSanityArticle {
...
}
}
However, this naive approach is not a solution, since any object type would then be available in the generated SDL (the check is obviously there for a reason).
Disable inference with @dontInfer:
This also results in a successful develop/build, but I will not be able to execute a query for allSanityArticle
.
What's the right solution to this problem?
What I would prefer is to extend the SanityArticle
type with implements Node
(and any other "root object types") so that I can query these in my Gatsby application (basically, treat "root object types" similar to "document types").
Note that, in this case, it is possible to remodel the application data (i.e. making the Article
a "document", but that's still not a solution to this problem).
Help would be much appreciated!
Thanks for the thorough report - this is an interesting problem.
I'm curious why you chose to have the article type as an object and not a document? Are you saying that you have documents of type article
, or are they always inline objects?
-
We can't add
Node
to all object types without also hoisting all objects to root-level gatsby nodes, sinceNode
requires you to specifyid
,parent
,children
andinternal
. We could hoist every object, but it would be a pretty big change. On the other hand, it would solve a weird case where an array that mixes references and inline objects requires us to hoist objects. It would also create a situation where you could query for inline objects, which may or may not be what you want. -
We could use
dontInfer
for object types, but that would prevent you from querying objects that are somehow created as top-level documents.
I'm still very new to Sanity, so I'm not familiar with the different terms, and I might also be modeling my application "incorrectly".
The reasoning for making the article an object instead of a document was for it to always be embedded inline in other documents, instead of it being a reference (to make for a better UX while editing different kind of content models). Still, in some cases it would still be nice to be able to get all articles independent of which documents they are embedded into.
Intuitively, I've thought that an object type defined in the top level scope would be its own collection/node type, and thus also be directly available in a query (in Gatsby, I still haven't tested/looked into GROQ). However, I'm realizing that this assumption might not be correct? Could it somehow be possible to configure this functionality, or is would the cleanest solution to this problem just be to make the "article" a document type instead?
Making it a document type still allows it to be embedded as an online object, so that may well be a good solution, but I'm not sure I see the whole picture. We still have to address this in the plugin, so I'm going to give it some more thought.
@rexxars Yeah, I realized that it could be a document right after my previous post, so I went back and changed it to an embedded article of type "document". This works, but embedded object can still not be queried directly - I'm assuming this is due to how the objects are persisted and queried, so I guess it's expected.
Now, I've also been reading through your documentation, and I can see that Create referenced documents in-place is on Sanity's roadmap. The whole reason for embedding the articles in the first place was better editing UX for the writers, but it seams like this feature would solve part of the problem I'm having here, so maybe I should just do:
- Let "article" be a document type
- Reference "article" in my other models instead of embedding it
- Wait for the feature to be implemented :)