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

[meta] Gatsby GraphQL Roadmap #12510

Closed
14 of 23 tasks
freiksenet opened this issue Mar 12, 2019 · 11 comments
Closed
14 of 23 tasks

[meta] Gatsby GraphQL Roadmap #12510

freiksenet opened this issue Mar 12, 2019 · 11 comments
Labels
topic: GraphQL Related to Gatsby's GraphQL layer type: documentation An issue or pull request for improving or updating Gatsby's documentation

Comments

@freiksenet
Copy link
Contributor

freiksenet commented Mar 12, 2019

With #12272 being close to be shipped, it's nice to have a more detailed roadmap on what we want to do next. This issue serves as such roadmap. Issues not in priority order.

Documentation issues

  • Guide for schema customization in Gatsby
  • Updated GraphQL API docs to take into account additions (like nodes)
  • Update GraphQL docs to include better info about inferrence, how it works, how type names are generated etc
  • API docs for type builders
  • Guide how to use Gatsby APIs (like files/images) with third-party schema (eg createRemoteFileNode in resolvers)
  • All GraphQL types should have documentation

Core improvements

  • Look at how we resolve filter/sort fields with resolvers and possibly abstract that out better
  • On-demand schema regeneration. For live reload of schema during development.
  • Use new graphql-compose extensions feature to store metadata about types, like whether it's generated, user defined or plugin defined (or maybe theme defined) and implement access control based on that . Use that to add inference options to type builders. Use that to add metadata about related composer and clear that when rebuilding type
  • Figure out how should plugins provider functionality as models
  • Figure out theme data model and how it all connects with schema refactoring
  • Figure out a better way to work with third-party schemas. It seems like a balance between "gatsby compatibility" and "uniformness with 3rd party API". Currently we are practically 100% to the latter, maybe we should figure a better balance.
  • Provide easier way to link nodes with foreign-key fields (other than the ___NODE naming convention which is currently tied to inference)
  • Decouple example value from resolvers. Don't run example value when not needed.
  • Move to explicit default resolvers (@date, @fileByRelativePath)

Nice to have things

  • Directives for simple resolver use cases like @file or @relativeFile
  • Extend connection types with all the goodies for connections (better paging, more meta information etc). Pretty low hanging fruit providing lots of value potentially.
  • Projection/fragments insider resolvers for easier third-party schema resolvers
  • Generate schema that can be put into createTypes based on current inferred schema
  • Print GraphQL schema that is currently generated
  • Make GraphQLDate a real Date type
  • Set max inference depth (deeper levels should be inferred as JSON)
  • Generate union types on scalar fields linking to multiple types with the ___NODE convention
@NickyMeuleman
Copy link
Contributor

Awwww yeah. This means soon, I won't have to dig into the Gatsby store to get the schema anymore?
https://github.com/NickyMeuleman/gatsby-plugin-extract-schema

@jserrao
Copy link
Contributor

jserrao commented Mar 15, 2019

Would be great to see if we can deal with the upstream issues around including GraphQL fragments in GraphiQL.

@freiksenet
Copy link
Contributor Author

@jserrao Could you link to the issue?

@jserrao
Copy link
Contributor

jserrao commented Mar 18, 2019

@freiksenet - I'm not sure anything is broken, but functionally it's non optimal DX.

The most Gatsby-related issue is around gatsby-image, which makes heavy use of fragments. Let's say a beginning Gatsby user wants to test how to do an image query...

On a Gatsby page, they would do something like this:

export const query = graphql`
  query {
    file(relativePath: { eq: "src/images/whatever.jpg" }) {
      childImageSharp {
        fixed(width: 125, height: 125) {
          ...GatsbyContentfulFluid_withWebp
        }
      }
    }
  }
`

If you get that working, that's a nice little confidence boost when you're trying out a new tool. But then In GraphiQL, you can't use ...GatsbyImageSharpFixed, so you've got to go look up what the fragment is to use it in GraphiQL:

  query {
    file(relativePath: { eq: "src/images/whatever.jpg" }) {
      childImageSharp {
        fixed(width: 125, height: 125) {
          aspectRatio
          base64
          sizes
          src
          srcSet
          srcSetWebp
          srcWebp
        }
      }
    }
  }

Obviously not the end of the world, but if we can get fragments into GraphiQL somehow, that would be a win.

@jlengstorf
Copy link
Contributor

jlengstorf commented Mar 19, 2019

I'm so into this new work! I've run into two things while playing with this.

  1. I think we need util functions for e.g. dealing with root query resolvers.
  2. We need a blessed best practice for creating node IDs in custom types.

Util function for making root query resolvers

For example, if I create a Post type:

exports.sourceNodes = ({ actions: { createTypes }, schema, reporter }) => {
  reporter.info('Adding the `Post` and `Author` types to the schema.');

  createTypes(`
    type Post implements Node {
      title: String!
    }
  `);
};

Gatsby will automatically create a post and allPost query. The schema includes edges, nodes, totalCount, etc. — plus there are query arguments.

If I want to implement a custom resolver, I currently need to provide all of that stuff, which feels cumbersome and likely to cause issues over time. (E.g. internals change; does that break all custom resolvers in userland?)

To address this, I'd love to see a utility function that does something like this:

function createGatsbyRootResolver(nodes) {
  // TODO do stuff to handle distinct and group fields
  return {
    nodes,
    edges: nodes.map(node => ({ node })),
    totalCount: nodes.length,
    // ...
  }
}

In userland, it could be supplied as a helper:

exports.createResolvers = ({ createResolvers, createGatsbyRootResolver }) => {
  createResolvers({
    Query: {
      post: {
        async resolve(_, args, context) {
          const post = await context.nodeModel.runQuery({
            query: args,
            type: 'MarkdownRemark',
            firstOnly: true
          });

          return mdToPost(post);
        }
      },
      allPost: {
        async resolve(_, args, context) {
          const posts = await context.nodeModel
            .runQuery({
              query: args,
              type: 'MarkdownRemark'
            });

          // Turns the array into a format compatible with the root resolver schema
          return createGatsbyRootResolver(posts);
        }
      }
    }
  });
};

If we don't do this, every custom type starts with broken queries by default.

Best practice for custom node IDs

Right now, the id field returns a non-null error on custom types if you try to query it.

In a perfect world, we'd auto-generate these somehow.

At minimum, we should have a canonical example of how to generate these IDs (and any other fields Gatsby requires and/or assumes will exist in documentation).

@freiksenet
Copy link
Contributor Author

freiksenet commented Mar 20, 2019

@jlengstorf I think with interfaces the id thing will be a bit easier because they'll always have the same ids as nodes of the underlying backing types. Also interfaces will get all the stuff inside the resolver automatically, so you wouldn't need to define it.

@docwhat
Copy link
Contributor

docwhat commented Mar 25, 2019

If I'm understanding it correctly; createTypes() would be used to specify part of the schema.

It would be nice if a user could just drop a gatsby/schema.graphql in their repository without having to monkey with the gatsby-node.js file. #11952 would need to detect and hash the .graphql file, though.

@angeloashmore
Copy link
Contributor

@freiksenet I see directives under "Nice to have things". Is there any way now to add custom directives? Possibly by exposing the schema composer?

schemaComposer.addDirective(InferDirective)
schemaComposer.addDirective(DontInferDirective)

@stefanprobst
Copy link
Contributor

@angeloashmore We don't plan to expose the schema composer directly. Next step is to expose some internals via extension/directive - for example to define foreign-key relations on fields. Once we are happy with the API for this, it would not be very hard to also allow registering custom extension/directive handlers.

@stefanprobst
Copy link
Contributor

@angeloashmore For custom directives, this is how it could look like: #13623

@amberleyromo amberleyromo changed the title [meta] Gatbsy GraphQL Roadmap [meta] Gatsby GraphQL Roadmap Jun 4, 2019
@lannonbr lannonbr added the topic: GraphQL Related to Gatsby's GraphQL layer label Aug 14, 2019
@freiksenet
Copy link
Contributor Author

Closing this as it's out of date and mostly done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: GraphQL Related to Gatsby's GraphQL layer type: documentation An issue or pull request for improving or updating Gatsby's documentation
Projects
None yet
Development

No branches or pull requests

9 participants