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

Missing data or fields in the GraphQL schema #59

Open
Simply007 opened this issue May 28, 2019 · 5 comments

Comments

@Simply007
Copy link
Member

commented May 28, 2019

Brief bug description

The issue is described in https://rshackleton.co.uk/articles/gotchas-and-workarounds-with-gatsby-and-kentico-cloud-part-1

Repro steps

  1. Create a content type with at least one text field
  2. Connect project to Gatsby
    (DON'T CREATE A CONTENT ITEM BASED ON THIS CONTENT TYPE)
  3. Query the content type
{
  allKenticoCloudItem<CONTENTTYPECODENAME> {
    edges {
      node {
        system {
          codename
        }
        elements {
          <ELEMENTNAME> {
            value
          }
        }
      }
    }
  }
}
  1. See error
{
  "errors": [
    {
      "message": "Cannot query field \"<CONTENTTYPECODENAME>\" on type \"Query\".",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ]
    }
  ]
}

Expected behavior

The query should return empty data without error.

Gatsby schema customization might solve the issue

GraphQL schema generator might help with implementation: https://github.com/Kentico/kentico-cloud-graphql-schema-generator

Additional context

Twitter feed: https://twitter.com/shackleberry112/status/1132245949491896320
@rshackleton's article with description how to implement the schema customization on the application https://rshackleton.co.uk/articles/learning-about-gatsby-schema-customisation-with-kontent-ai

@Simply007

This comment has been minimized.

Copy link
Member Author

commented May 28, 2019

The current workaround is to create a dummy item for all content types with all the fields filled as it is in WordPress:
gatsbyjs/gatsby#5296

@rshackleton

This comment has been minimized.

Copy link

commented Aug 27, 2019

@Simply007 are we in a position to be able to resolve this issue now with the new schema customisation API?

https://github.com/gatsbyjs/gatsby/blob/master/docs/docs/schema-customization.md

Specifically the ability to opt-out of type inference and therefore specify custom types for fields:

https://github.com/gatsbyjs/gatsby/blob/master/docs/docs/schema-customization.md#opting-out-of-type-inference

It seems like this would allow the schema to properly match the Kentico Cloud JS SDK and will avoid the issue of missing fields when data is unavailable.

@rshackleton

This comment has been minimized.

Copy link

commented Aug 27, 2019

Current Problems

To be honest it feels like a source plugin based on a dynamic schema like Kentico Cloud should opt for Type Builders - https://www.gatsbyjs.org/docs/schema-customization/#gatsby-type-builders

This should allow types to be constructed from scratch. There are many types which should be defined once and shared, for example:

  • System: Duplicated for each content model e.g. "KenticoCloudItemHomePageSystem", "KenticoCloudItemBlogPostSystem" etc
  • Field Types: All field types are duplicated for each field and model, regardless of whether they're of the same data type in Kentico Cloud. For example a Text field on two models will have a different type, "KenticoCloudItemHomePageElementsIntro" and "KenticoCloudItemHomePageElementsMetadata__page_title".
  • Assets: All assets are different types unqiue to their associated field. This means that if a single type has an asset field without an image then that particular field will be missing data. Even worse, if that image happens to be missing a description in Kentico Cloud then that one instance of the image will be missing the "description" field. This can lead to super awkward bugs.

However, probably the worst thing for a consumer of the plugin is that all of these issues are so difficult to fix using the new schema customization as the original type definition produces so many unique types. Currently if we wanted to add a resolver to all Asset fields we would need to manually add a resolver to each unique Asset field by name, e.g.:

  • KenticoCloudItemHomePageElementsMetadata__open_graph_image
  • KenticoCloudItemBlogPostElementsMetadata__open_graph_image

These are both Asset fields, from the same content type snippet on two different content models. However they result in two different types being created.

Future Opportunities

Also, on the topic of content type snippets. The schema customization API opens up some serious opportunities to make the schema more composable and usable when querying. For example, if we had two different types that use the same content type snippet there could be an interface defined to make sure these fields are shared:

interface SnippetMetadata {
  metadata__page_title: String!
  metadata__page_description: String!
  metadata__page_keywords: String!
}

type KenticoCloudItemHomePage implements Node & SnippetMetadata {
  metadata__page_title: String!
  metadata__page_description: String!
  metadata__page_keywords: String!
}

type KenticoCloudItemBlogPost implements Node & SnippetMetadata {
  metadata__page_title: String!
  metadata__page_description: String!
  metadata__page_keywords: String!
}

Furthermore, fragments could then be used to make querying types for specific snippets even easier!

{
  fragment SnippetMetadataFragment on SnippetMetadata {
    metadata__page_title
    metadata__page_description
    metadata__page_keywords
  }

  allKenticoCloudItemHomePage {
    edges {
      node {
        elements {
          ...SnippetMetadataFragment
        }
      }
    }
  }

  allKenticoCloudItemBlogPost {
    edges {
      node {
        elements {
          ...SnippetMetadataFragment
        }
      }
    }
  }
}

Note: I've simplified what a field is here, really they would need to share some other complex type such as TextField with the appropriate name, type, value properties.

Summary

I think the next major version (v7?) should be focused on re-architecting the type generation to use the new schema customisation API. The benefits to be gained are enormous, it will make the schema much more sane and predictable and should mean the plugin is subject to fewer bugs and mean consumers can get on with the important things... Like building awesome and fast websites! 😊

Sorry for the wall of text!

@rshackleton

This comment has been minimized.

Copy link

commented Sep 20, 2019

An update on my previous comment, I've put together a POC for the explicit type generation.

https://github.com/rshackleton/gatsby-site-playground/blob/master/plugins/gatsby-source-kontent-rs/gatsby-node.js

Currently this does the following:

  • Defines some static GraphQL types for the system property and also for the TextElement field type.
  • Creates explicit types for each Content Type using the Type Builder API
  • Defines an interface KontentItem which allows all content items to be queried at the top level using allKontentItem which could be a useful utility for sitemaps etc.
  • Creates nodes using those types for each Content Item in the Kontent project

In it's current state the schema displays all possible fields on a particular type, most are defined with basic scalar types as the Element specific types are not yet defined.

image

Also I've not looked at any resolution of linked items or rich text yet.

Anyway, felt this could be a good reference point for this issue to be looked at.

@rshackleton

This comment has been minimized.

Copy link

commented Sep 21, 2019

Latest updates to my POC have added support for modular_content fields via the @link directive.

type KontentModularContentElement implements KontentElement @infer {
  name: String!
  type: String!
  value: [KontentItem] @link(by: "system.codename")
}

This results in a field that handles null values, always has the KontentItem interface as it's value type and can therefore be spread across to access type-specific fields:

query MyQuery {
  allKontentItemAbout {
    nodes {
      elements {
        sectionsSections {
          value {
            system {
              type
            }
            ... on KontentItemTwinColumnSection {
              id
              elements {
                title {
                  value
                }
              }
            }
          }
        }
      }
    }
  }
}
{
  "data": {
    "allKontentItemAbout": {
      "nodes": [
        {
          "elements": {
            "sectionsSections": {
              "value": null
            }
          }
        },
        {
          "elements": {
            "sectionsSections": {
              "value": [
                {
                  "system": {
                    "type": "twin_column_section"
                  },
                  "id": "97ff5c85-4f37-5666-8852-b54817934702",
                  "elements": {
                    "title": {
                      "value": "The Project"
                    }
                  }
                },
                {
                  "system": {
                    "type": "triple_column"
                  }
                },
                {
                  "system": {
                    "type": "partnership"
                  }
                }
              ]
            }
          }
        }
      ]
    }
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
3 participants
You can’t perform that action at this time.