-
Notifications
You must be signed in to change notification settings - Fork 10.3k
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
[source-contentful] If entry is not set by user, provide an empty value of the same type #2037
[source-contentful] If entry is not set by user, provide an empty value of the same type #2037
Conversation
trying to address #1517 |
Deploy preview ready! Built with commit 34a67cf |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, just a few comments.
Can you add some unit test to make sure you didn't miss an edge case, like localized fields etc?
Also maybe @KyleAMathews can give more input?
entryItemFields[fieldName] = "" | ||
} else if (contentTypeItemField.type.match(/Number/)) { | ||
// NOTE: Might be a problem for some people to auto set to 0? | ||
entryItemFields[fieldName] = 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since Number(undefined) === NaN
let's set the default to NaN
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point. Thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah other than missing tests, looks very reasonable and mergeable!
@@ -111,7 +111,7 @@ exports.buildForeignReferenceMap = ({ | |||
} | |||
foreignReferenceMap[v.sys.id].push({ | |||
name: `${contentTypeItemId}___NODE`, | |||
id: entryItem.sys.id, | |||
id: entryItem.sys.id |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please run "npm run format" from the root of the repo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ooh so that's the trick! ok thanks
entryItemFields[fieldName] = "" | ||
} else if (contentTypeItemField.type.match(/Number/)) { | ||
// NOTE: Might be a problem for some people to auto set to 0? | ||
entryItemFields[fieldName] = 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
Of course I forgot about tests! I am not familiar with the test workflow so I might be coming back with questions. I'll try and dive in today or tomorrow. |
@MarcCoet you can check the existing tests for the plugin and add to it |
) { | ||
entryItemFields[fieldName] = {} | ||
} else if (contentTypeItemField.type.match(/Array/)) { | ||
entryItemFields[fieldName] = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
something that could be problematic I guess (it is for me at least) is that []
and {}
are truthy, and these fields are obviously nullable in Contentful or we wouldn't be here :). I have code like this { data.someField || "Doesn't exist" }
and I imagine that's pretty common. Anyway, I still think this is better than what I'm doing now (making sure the field exists in a placeholder entity in contentful).
dan-weaver's comment made me dig a little more and a few problems showed up. Please bare with me because I'll need guidance if we want to take this a step further. (Context: I am still investigating jest so this is purely based on trial and error)
While this is a somehow relatively working solution for arrays of strings, it miserably fails for assets, arrays of assets, references (with blank fields), arrays of references, ... IF we want to go that way and set empty fields inside empty fields (?) then my question is: is the sync API handling an "include" parameter? It does not seem so and even though I am not super familiar with the Contentful API I guess this might be a problem because we can't see easily inside Link entries... With a more global concern in mind, I am wondering why we don't just authorize developers to query fields that does not exist. I mean if I want to be a punk and query a bunch of stuff that does not exist in the schema, I would gladly see a big fat warning in the console but then go on with the rest of the query. That way, if I expect that query to be valid at some point in the future it is already in place.
and makes everything fail. Does it really have to be that drastic @KyleAMathews ? Back to the problem at hand: I still think this PR handles part of the problem so I'll get back to my tests ASAP. |
I feel like the best way to implement tests is to add empty fields to the demo space and update the snapshot. I updated the current snapshot but there are only blank fields on strings and arrays of strings. |
"type": "ContentfulBrand", | ||
}, | ||
"logo___NODE": "c4zj1ZOfHgQ8oqgaSKm4Qo2", | ||
"node_locale": "en-US", | ||
"parent": "Brand", | ||
"phone": Array [ | ||
"", | ||
], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it something we want or should I leave it like an empty array (please see my long comment above for details on why I changed that)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah we'd need this or else the schema would be wrong e.g. Gatsby wouldn't know that phone is an array of strings.
This could be desirable perhaps but GraphQL says otherwise so you'd need to take the question to them :-) |
300de3e
to
34a67cf
Compare
if (contentTypeItemField.type === `Object`) { | ||
if (typeof entryItemFields[fieldName].json === `undefined`) { | ||
entryItemFields[fieldName].json = JSON.stringify( | ||
entryItemFields[fieldName] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a proposition to solve #1703
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of converting every object to string, I added a json property to every object containing the stringified version of the object. This means we can query that json field on any object even if the object content vary from entry to entry.
Does that make sense?
Should we choose a wiser property name?
I would like to add support for non existant entries, meaning if there is e.g. a blogpost content type but no entry of that type is created in contentful then we can still query those blogposts and get 'blank values' for each field. |
What's the status of this? Any way I can help carry forward? |
Contrary to the PR title, this concerns actually all source types, not just contentful. Right now (from memory), e.g. if cloning the gatsby website and removing some field from all blog posts (e.g. There should ideally be a way to intercept the node creation to add any needed default values to a specific GraphQL type. |
This is especially needed for auto-generated field types, such as the blog post |
@sedubois you are right. From what I've seen the most interesting discussion on the topic is #2392. |
@lsirivong pinged me about how to get this in — I think conceptually it's sound — we want code which double checks that the entire schema is translated correctly from Contentful to Gatsby & fills in missing pieces. What I'd like improved here is there needs to be a lot more tests as this is a tricky thing to do correctly so we need to ensure things are solid. |
@sedubois totally agree — but this isn't solvable (directly) unfortunately in most source plugins. Contentful is unique in that we can get access to the actual schema for different content types where on e.g. gatsbyjs.org — there is no defined schema other than the data we add to various files. One way solve this (worth pursuing on another issue) is Gatsby let you attach schemas perhaps written in GraphQL's IDL language to source plugins to use for their schemas to replace the inferred schema. |
@MarcCoet @KyleAMathews What is currently holding you back from merging this? There should be more tests? Can I do anything to help? |
We have an interest in this for our gatsby/ contentful integration as well. Depending what changes are needed, we could lend one of our developers to carry this work over the line in the next couple of weeks. Just let us know @KyleAMathews @MarcCoet |
@hirviid @PepperTeasdale thanks for stepping in. From what I understood it is lacking some tests and a way to add them could be to complexify the data that is being used to create the test snapshot. If you have time or ressource available to work on this, you may want to find a better solution than this one though. As Kyle said above, the best solution might be to infer the GraphQL schema from Contentful content types. |
I want to bring up one more complex use case that's come up in my project. We have one model called a This allows for flexible, modular pages. The graphql looks like this:
Given this structure and the fact that I have about 10 of these module types, my build currently fails unless each of these models is used at least once on a I looked into extending this PR to deal with complex relations like this but hit a dead end. Not only would I need to create a placeholder Or maybe my schema is just too complicated :) |
@sarahatwork best way I found to avoid that is create in advance an instance of every content type and link them together at every possible place. I called all these entries 'IGNORE' and told editors to... ignore them. Then in my queries, I do the same. I am also in favor of the #3344 approach as it will allow far more opportunities and it is CMS agnostic. |
👋 @sarahatwork |
@MarcCoet Yeah I'm moving ahead with a dummy entry approach now while waiting for a real fix. Instead of ruling out by name I've made a new |
Hey @sarahatwork I think I was a bit confused. is the modules field one single ref field or multiple references? |
@Khaledgarbaya It's the type "References, many" in Contentful. Here's one in action on one of our content pages: |
ok, I totally misunderstood you in the previous comment, sorry about that, I am also in favor of #3344 to solve the problem once and for all. |
Closing this as we all agree #3344 is a better approach. |
quick and dirty solution to allow 'blank' fields in contentful.
Sorry for the noise on closing commas. Prettier stepped in.
Would love a review and some tests on different data sets.
@Khaledgarbaya your input is more than welcome too. ;)